common.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*!
  2. @file
  3. Forward declares `boost::hana::common` and `boost::hana::common_t`.
  4. @copyright Louis Dionne 2013-2017
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef BOOST_HANA_FWD_CORE_COMMON_HPP
  9. #define BOOST_HANA_FWD_CORE_COMMON_HPP
  10. #include <boost/hana/config.hpp>
  11. BOOST_HANA_NAMESPACE_BEGIN
  12. //! @ingroup group-core
  13. //! %Metafunction returning the common data type between two data types.
  14. //!
  15. //! `common` is a natural extension of the `std::common_type` metafunction
  16. //! to data types. Given two data types `T` and `U`, we say that they share
  17. //! a common type `C` if both objects of data type `T` and objects of data
  18. //! type `U` may be converted (using `to`) to an object of data type `C`,
  19. //! and if that conversion is equality preserving. In other words, this
  20. //! means that for any objects `t1, t2` of data type `T` and `u1, u2` of
  21. //! data type `U`, the following law is satisfied:
  22. //! @code
  23. //! to<C>(t1) == to<C>(t2) if and only if t1 == t2
  24. //! to<C>(u1) == to<C>(u2) if and only if u1 == u2
  25. //! @endcode
  26. //!
  27. //! The role of `common` is to provide an alias to such a `C` if it exists.
  28. //! In other words, if `T` and `U` have a common data type `C`,
  29. //! `common<T, U>::%type` is an alias to `C`. Otherwise, `common<T, U>`
  30. //! has no nested `type` and can be used in dependent contexts to exploit
  31. //! SFINAE. By default, the exact steps followed by `common` to determine
  32. //! the common type `C` of `T` and `U` are
  33. //! 1. If `T` and `U` are the same, then `C` is `T`.
  34. //! 2. Otherwise, if `true ? std::declval<T>() : std::declval<U>()` is
  35. //! well-formed, then `C` is the type of this expression after using
  36. //! `std::decay` on it. This is exactly the type that would have been
  37. //! returned by `std::common_type`, except that custom specializations
  38. //! of `std::common_type` are not taken into account.
  39. //! 3. Otherwise, no common data type is detected and `common<T, U>` does
  40. //! not have a nested `type` alias, unless it is specialized explicitly.
  41. //!
  42. //! As point 3 suggests, it is also possible (and sometimes necessary) to
  43. //! specialize `common` in the `boost::hana` namespace for pairs of custom
  44. //! data types when the default behavior of `common` is not sufficient.
  45. //! Note that `when`-based specialization is supported when specializing
  46. //! `common` in the `boost::hana` namespace.
  47. //!
  48. //! > #### Rationale for requiring the conversion to be equality-preserving
  49. //! > This decision is aligned with a proposed concept design for the
  50. //! > standard library ([N3351][1]). Also, if we did not require this,
  51. //! > then all data types would trivially share the common data type
  52. //! > `void`, since all objects can be converted to it.
  53. //!
  54. //!
  55. //! Example
  56. //! -------
  57. //! @include example/core/common/common.cpp
  58. //!
  59. //!
  60. //! [1]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3351.pdf
  61. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  62. template <typename T, typename U, optional when-based enabler>
  63. struct common { see documentation };
  64. #else
  65. template <typename T, typename U, typename = void>
  66. struct common;
  67. #endif
  68. //! @ingroup group-core
  69. //! %Metafunction returning whether two data types share a common data type.
  70. //!
  71. //! Given two data types `T` and `U`, this metafunction simply returns
  72. //! whether `common<T, U>::%type` is well-formed.
  73. //!
  74. //!
  75. //! Example
  76. //! -------
  77. //! @include example/core/common/has_common.cpp
  78. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  79. template <typename T, typename U>
  80. struct has_common { whether common<T, U>::type is well-formed };
  81. #else
  82. template <typename T, typename U, typename = void>
  83. struct has_common;
  84. #endif
  85. //! @ingroup group-core
  86. //! Alias to `common<T, U>::%type`, provided for convenience.
  87. //!
  88. //!
  89. //! Example
  90. //! -------
  91. //! @include example/core/common/common_t.cpp
  92. template <typename T, typename U>
  93. using common_t = typename common<T, U>::type;
  94. BOOST_HANA_NAMESPACE_END
  95. #endif // !BOOST_HANA_FWD_CORE_COMMON_HPP