]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*! |
2 | @file | |
3 | Defines `boost::hana::common` and `boost::hana::common_t`. | |
4 | ||
5 | @copyright Louis Dionne 2013-2016 | |
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 |