common.hpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /*!
  2. @file
  3. Defines `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_CORE_COMMON_HPP
  9. #define BOOST_HANA_CORE_COMMON_HPP
  10. #include <boost/hana/fwd/core/common.hpp>
  11. #include <boost/hana/concept/constant.hpp>
  12. #include <boost/hana/config.hpp>
  13. #include <boost/hana/core/when.hpp>
  14. #include <boost/hana/detail/canonical_constant.hpp>
  15. #include <boost/hana/detail/std_common_type.hpp>
  16. #include <boost/hana/detail/void_t.hpp>
  17. #include <type_traits>
  18. BOOST_HANA_NAMESPACE_BEGIN
  19. //////////////////////////////////////////////////////////////////////////
  20. // common
  21. //////////////////////////////////////////////////////////////////////////
  22. //! @cond
  23. template <typename T, typename U, typename>
  24. struct common : common<T, U, when<true>> { };
  25. //! @endcond
  26. template <typename T, typename U, bool condition>
  27. struct common<T, U, when<condition>>
  28. : detail::std_common_type<T, U>
  29. { };
  30. template <typename T>
  31. struct common<T, T> {
  32. using type = T;
  33. };
  34. //////////////////////////////////////////////////////////////////////////
  35. // has_common
  36. //////////////////////////////////////////////////////////////////////////
  37. template <typename T, typename U, typename>
  38. struct has_common : std::false_type { };
  39. template <typename T, typename U>
  40. struct has_common<T, U, detail::void_t<typename common<T, U>::type>>
  41. : std::true_type
  42. { };
  43. //////////////////////////////////////////////////////////////////////////
  44. // Provided common data types for Constants
  45. //////////////////////////////////////////////////////////////////////////
  46. namespace constant_detail {
  47. //! @todo
  48. //! This is an awful hack to avoid having
  49. //! @code
  50. //! common<integral_constant_tag<int>, integral_constant_tag<long>>
  51. //! ==
  52. //! CanonicalConstant<long>
  53. //! @endcode
  54. template <typename A, typename B, typename C>
  55. struct which {
  56. using type = detail::CanonicalConstant<C>;
  57. };
  58. template <template <typename ...> class A, typename T, typename U, typename C>
  59. struct which<A<T>, A<U>, C> {
  60. using type = A<C>;
  61. };
  62. }
  63. template <typename A, typename B>
  64. struct common<A, B, when<
  65. hana::Constant<A>::value &&
  66. hana::Constant<B>::value &&
  67. has_common<typename A::value_type, typename B::value_type>::value
  68. >> {
  69. using type = typename constant_detail::which<
  70. A, B,
  71. typename common<typename A::value_type,
  72. typename B::value_type>::type
  73. >::type;
  74. };
  75. template <typename A, typename B>
  76. struct common<A, B, when<
  77. hana::Constant<A>::value &&
  78. !hana::Constant<B>::value &&
  79. has_common<typename A::value_type, B>::value
  80. >> {
  81. using type = typename common<typename A::value_type, B>::type;
  82. };
  83. template <typename A, typename B>
  84. struct common<A, B, when<
  85. !hana::Constant<A>::value &&
  86. hana::Constant<B>::value &&
  87. has_common<A, typename B::value_type>::value
  88. >> {
  89. using type = typename common<A, typename B::value_type>::type;
  90. };
  91. BOOST_HANA_NAMESPACE_END
  92. #endif // !BOOST_HANA_CORE_COMMON_HPP