1 /*! 2 @file 3 Defines `boost::hana::detail::CanonicalConstant`. 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_DETAIL_CANONICAL_CONSTANT_HPP 11 #define BOOST_HANA_DETAIL_CANONICAL_CONSTANT_HPP 12 13 #include <boost/hana/config.hpp> 14 15 16 BOOST_HANA_NAMESPACE_BEGIN namespace detail { 17 //! @ingroup group-details 18 //! Tag representing a canonical `Constant`. 19 //! 20 //! This is an implementation detail used to provide many models for 21 //! stuff like `Monoid`, `Group`, etc. To create a `CanonicalConstant`, 22 //! simply create an object with a nested `hana_tag` equal to the proper 23 //! specialization of `CanonicalConstant<T>`, and then also provide a 24 //! `constexpr` static member `::%value` holding the value of the constant. 25 template <typename T> 26 struct CanonicalConstant { 27 using value_type = T; 28 }; 29 } BOOST_HANA_NAMESPACE_END 30 31 32 #include <boost/hana/concept/constant.hpp> 33 #include <boost/hana/concept/integral_constant.hpp> 34 #include <boost/hana/core/to.hpp> 35 #include <boost/hana/core/when.hpp> 36 37 #include <type_traits> 38 39 40 BOOST_HANA_NAMESPACE_BEGIN 41 ////////////////////////////////////////////////////////////////////////// 42 // Constant 43 ////////////////////////////////////////////////////////////////////////// 44 template <typename T> 45 struct value_impl<detail::CanonicalConstant<T>> { 46 template <typename X> applyvalue_impl47 static constexpr decltype(auto) apply() 48 { return X::value; } 49 }; 50 51 namespace detail { 52 template <typename T, typename X> 53 struct canonical_constant { 54 static constexpr auto value = hana::to<T>(hana::value<X>()); 55 using hana_tag = detail::CanonicalConstant<T>; 56 }; 57 } 58 59 template <typename T, typename C> 60 struct to_impl<detail::CanonicalConstant<T>, C, when< 61 hana::Constant<C>::value && 62 is_convertible<typename C::value_type, T>::value 63 >> 64 : embedding<is_embedded<typename C::value_type, T>::value> 65 { 66 template <typename X> applyto_impl67 static constexpr detail::canonical_constant<T, X> apply(X const&) 68 { return {}; } 69 }; 70 71 ////////////////////////////////////////////////////////////////////////// 72 // IntegralConstant (when value_type is integral) 73 ////////////////////////////////////////////////////////////////////////// 74 template <typename T> 75 struct IntegralConstant<detail::CanonicalConstant<T>> { 76 static constexpr bool value = std::is_integral<T>::value; 77 }; 78 BOOST_HANA_NAMESPACE_END 79 80 #endif // !BOOST_HANA_DETAIL_CANONICAL_CONSTANT_HPP 81