1 /*! 2 @file 3 Forward declares `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_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 104