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