]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*! |
2 | @file | |
3 | Forward declares `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_FWD_CORE_COMMON_HPP | |
11 | #define BOOST_HANA_FWD_CORE_COMMON_HPP | |
12 | ||
13 | #include <boost/hana/config.hpp> | |
14 | ||
15 | ||
16 | BOOST_HANA_NAMESPACE_BEGIN | |
17 | //! @ingroup group-core | |
18 | //! %Metafunction returning the common data type between two data types. | |
19 | //! | |
20 | //! `common` is a natural extension of the `std::common_type` metafunction | |
21 | //! to data types. Given two data types `T` and `U`, we say that they share | |
22 | //! a common type `C` if both objects of data type `T` and objects of data | |
23 | //! type `U` may be converted (using `to`) to an object of data type `C`, | |
24 | //! and if that conversion is equality preserving. In other words, this | |
25 | //! means that for any objects `t1, t2` of data type `T` and `u1, u2` of | |
26 | //! data type `U`, the following law is satisfied: | |
27 | //! @code | |
28 | //! to<C>(t1) == to<C>(t2) if and only if t1 == t2 | |
29 | //! to<C>(u1) == to<C>(u2) if and only if u1 == u2 | |
30 | //! @endcode | |
31 | //! | |
32 | //! The role of `common` is to provide an alias to such a `C` if it exists. | |
33 | //! In other words, if `T` and `U` have a common data type `C`, | |
34 | //! `common<T, U>::%type` is an alias to `C`. Otherwise, `common<T, U>` | |
35 | //! has no nested `type` and can be used in dependent contexts to exploit | |
36 | //! SFINAE. By default, the exact steps followed by `common` to determine | |
37 | //! the common type `C` of `T` and `U` are | |
38 | //! 1. If `T` and `U` are the same, then `C` is `T`. | |
39 | //! 2. Otherwise, if `true ? std::declval<T>() : std::declval<U>()` is | |
40 | //! well-formed, then `C` is the type of this expression after using | |
41 | //! `std::decay` on it. This is exactly the type that would have been | |
42 | //! returned by `std::common_type`, except that custom specializations | |
43 | //! of `std::common_type` are not taken into account. | |
44 | //! 3. Otherwise, no common data type is detected and `common<T, U>` does | |
45 | //! not have a nested `type` alias, unless it is specialized explicitly. | |
46 | //! | |
47 | //! As point 3 suggests, it is also possible (and sometimes necessary) to | |
48 | //! specialize `common` in the `boost::hana` namespace for pairs of custom | |
49 | //! data types when the default behavior of `common` is not sufficient. | |
50 | //! Note that `when`-based specialization is supported when specializing | |
51 | //! `common` in the `boost::hana` namespace. | |
52 | //! | |
53 | //! > #### Rationale for requiring the conversion to be equality-preserving | |
54 | //! > This decision is aligned with a proposed concept design for the | |
55 | //! > standard library ([N3351][1]). Also, if we did not require this, | |
56 | //! > then all data types would trivially share the common data type | |
57 | //! > `void`, since all objects can be converted to it. | |
58 | //! | |
59 | //! | |
60 | //! Example | |
61 | //! ------- | |
62 | //! @include example/core/common/common.cpp | |
63 | //! | |
64 | //! | |
65 | //! [1]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3351.pdf | |
66 | #ifdef BOOST_HANA_DOXYGEN_INVOKED | |
67 | template <typename T, typename U, optional when-based enabler> | |
68 | struct common { see documentation }; | |
69 | #else | |
70 | template <typename T, typename U, typename = void> | |
71 | struct common; | |
72 | #endif | |
73 | ||
74 | //! @ingroup group-core | |
75 | //! %Metafunction returning whether two data types share a common data type. | |
76 | //! | |
77 | //! Given two data types `T` and `U`, this metafunction simply returns | |
78 | //! whether `common<T, U>::%type` is well-formed. | |
79 | //! | |
80 | //! | |
81 | //! Example | |
82 | //! ------- | |
83 | //! @include example/core/common/has_common.cpp | |
84 | #ifdef BOOST_HANA_DOXYGEN_INVOKED | |
85 | template <typename T, typename U> | |
86 | struct has_common { whether common<T, U>::type is well-formed }; | |
87 | #else | |
88 | template <typename T, typename U, typename = void> | |
89 | struct has_common; | |
90 | #endif | |
91 | ||
92 | //! @ingroup group-core | |
93 | //! Alias to `common<T, U>::%type`, provided for convenience. | |
94 | //! | |
95 | //! | |
96 | //! Example | |
97 | //! ------- | |
98 | //! @include example/core/common/common_t.cpp | |
99 | template <typename T, typename U> | |
100 | using common_t = typename common<T, U>::type; | |
101 | BOOST_HANA_NAMESPACE_END | |
102 | ||
103 | #endif // !BOOST_HANA_FWD_CORE_COMMON_HPP |