1 // Copyright Louis Dionne 2013-2017
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
4 
5 #include <boost/hana/assert.hpp>
6 #include <boost/hana/equal.hpp>
7 #include <boost/hana/monadic_fold_left.hpp>
8 #include <boost/hana/optional.hpp>
9 #include <boost/hana/traits.hpp>
10 #include <boost/hana/tuple.hpp>
11 #include <boost/hana/type.hpp>
12 
13 #include <type_traits>
14 namespace hana = boost::hana;
15 
16 
17 auto builtin_common_t = hana::sfinae([](auto&& t, auto&& u) -> hana::type<
18     std::decay_t<decltype(true ? hana::traits::declval(t) : hana::traits::declval(u))>
__anonc46602680102(auto&& t, auto&& u) 19 > { return {}; });
20 
21 template <typename ...T>
22 struct common_type { };
23 
24 template <typename T, typename U>
25 struct common_type<T, U>
26     : std::conditional_t<std::is_same<std::decay_t<T>, T>{} &&
27                          std::is_same<std::decay_t<U>, U>{},
28         decltype(builtin_common_t(hana::type_c<T>, hana::type_c<U>)),
29         common_type<std::decay_t<T>, std::decay_t<U>>
30     >
31 { };
32 
33 template <typename T1, typename ...Tn>
34 struct common_type<T1, Tn...>
35     : decltype(hana::monadic_fold_left<hana::optional_tag>(
36         hana::tuple_t<Tn...>,
37         hana::type_c<std::decay_t<T1>>,
38         hana::sfinae(hana::metafunction<common_type>)
39     ))
40 { };
41 
42 template <typename ...Ts>
43 using common_type_t = typename common_type<Ts...>::type;
44 
45 BOOST_HANA_CONSTANT_CHECK(
46   builtin_common_t(hana::type_c<int>, hana::type_c<float>)
47     ==
48   hana::just(hana::type_c<float>)
49 );
50 
51 static_assert(std::is_same<
52     common_type_t<char, short, char, short>,
53     int
54 >{}, "");
55 
56 static_assert(std::is_same<
57     common_type_t<char, double, short, char, short, double>,
58     double
59 >{}, "");
60 
61 static_assert(std::is_same<
62     common_type_t<char, short, float, short>,
63     float
64 >{}, "");
65 
66 static_assert(
67     hana::sfinae(hana::metafunction<common_type>)(
68         hana::type_c<int>, hana::type_c<int>, hana::type_c<int*>
69     ) == hana::nothing
70 , "");
71 
main()72 int main() { }
73