1 /*! 2 @file 3 Defines `boost::hana::common` and `boost::hana::common_t`. 4 5 @copyright Louis Dionne 2013-2017 6 Distributed under the Boost Software License, Version 1.0. 7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 8 */ 9 10 #ifndef BOOST_HANA_CORE_COMMON_HPP 11 #define BOOST_HANA_CORE_COMMON_HPP 12 13 #include <boost/hana/fwd/core/common.hpp> 14 15 #include <boost/hana/concept/constant.hpp> 16 #include <boost/hana/config.hpp> 17 #include <boost/hana/core/when.hpp> 18 #include <boost/hana/detail/canonical_constant.hpp> 19 #include <boost/hana/detail/std_common_type.hpp> 20 #include <boost/hana/detail/void_t.hpp> 21 22 #include <type_traits> 23 24 25 BOOST_HANA_NAMESPACE_BEGIN 26 ////////////////////////////////////////////////////////////////////////// 27 // common 28 ////////////////////////////////////////////////////////////////////////// 29 //! @cond 30 template <typename T, typename U, typename> 31 struct common : common<T, U, when<true>> { }; 32 //! @endcond 33 34 template <typename T, typename U, bool condition> 35 struct common<T, U, when<condition>> 36 : detail::std_common_type<T, U> 37 { }; 38 39 template <typename T> 40 struct common<T, T> { 41 using type = T; 42 }; 43 44 ////////////////////////////////////////////////////////////////////////// 45 // has_common 46 ////////////////////////////////////////////////////////////////////////// 47 template <typename T, typename U, typename> 48 struct has_common : std::false_type { }; 49 50 template <typename T, typename U> 51 struct has_common<T, U, detail::void_t<typename common<T, U>::type>> 52 : std::true_type 53 { }; 54 55 ////////////////////////////////////////////////////////////////////////// 56 // Provided common data types for Constants 57 ////////////////////////////////////////////////////////////////////////// 58 namespace constant_detail { 59 //! @todo 60 //! This is an awful hack to avoid having 61 //! @code 62 //! common<integral_constant_tag<int>, integral_constant_tag<long>> 63 //! == 64 //! CanonicalConstant<long> 65 //! @endcode 66 template <typename A, typename B, typename C> 67 struct which { 68 using type = detail::CanonicalConstant<C>; 69 }; 70 71 template <template <typename ...> class A, typename T, typename U, typename C> 72 struct which<A<T>, A<U>, C> { 73 using type = A<C>; 74 }; 75 } 76 77 template <typename A, typename B> 78 struct common<A, B, when< 79 hana::Constant<A>::value && 80 hana::Constant<B>::value && 81 has_common<typename A::value_type, typename B::value_type>::value 82 >> { 83 using type = typename constant_detail::which< 84 A, B, 85 typename common<typename A::value_type, 86 typename B::value_type>::type 87 >::type; 88 }; 89 90 template <typename A, typename B> 91 struct common<A, B, when< 92 hana::Constant<A>::value && 93 !hana::Constant<B>::value && 94 has_common<typename A::value_type, B>::value 95 >> { 96 using type = typename common<typename A::value_type, B>::type; 97 }; 98 99 template <typename A, typename B> 100 struct common<A, B, when< 101 !hana::Constant<A>::value && 102 hana::Constant<B>::value && 103 has_common<A, typename B::value_type>::value 104 >> { 105 using type = typename common<A, typename B::value_type>::type; 106 }; 107 BOOST_HANA_NAMESPACE_END 108 109 #endif // !BOOST_HANA_CORE_COMMON_HPP 110