canonical_constant.hpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*!
  2. @file
  3. Defines `boost::hana::detail::CanonicalConstant`.
  4. @copyright Louis Dionne 2013-2017
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef BOOST_HANA_DETAIL_CANONICAL_CONSTANT_HPP
  9. #define BOOST_HANA_DETAIL_CANONICAL_CONSTANT_HPP
  10. #include <boost/hana/config.hpp>
  11. BOOST_HANA_NAMESPACE_BEGIN namespace detail {
  12. //! @ingroup group-details
  13. //! Tag representing a canonical `Constant`.
  14. //!
  15. //! This is an implementation detail used to provide many models for
  16. //! stuff like `Monoid`, `Group`, etc. To create a `CanonicalConstant`,
  17. //! simply create an object with a nested `hana_tag` equal to the proper
  18. //! specialization of `CanonicalConstant<T>`, and then also provide a
  19. //! `constexpr` static member `::%value` holding the value of the constant.
  20. template <typename T>
  21. struct CanonicalConstant {
  22. using value_type = T;
  23. };
  24. } BOOST_HANA_NAMESPACE_END
  25. #include <boost/hana/concept/constant.hpp>
  26. #include <boost/hana/concept/integral_constant.hpp>
  27. #include <boost/hana/core/to.hpp>
  28. #include <boost/hana/core/when.hpp>
  29. #include <type_traits>
  30. BOOST_HANA_NAMESPACE_BEGIN
  31. //////////////////////////////////////////////////////////////////////////
  32. // Constant
  33. //////////////////////////////////////////////////////////////////////////
  34. template <typename T>
  35. struct value_impl<detail::CanonicalConstant<T>> {
  36. template <typename X>
  37. static constexpr decltype(auto) apply()
  38. { return X::value; }
  39. };
  40. namespace detail {
  41. template <typename T, typename X>
  42. struct canonical_constant {
  43. static constexpr auto value = hana::to<T>(hana::value<X>());
  44. using hana_tag = detail::CanonicalConstant<T>;
  45. };
  46. }
  47. template <typename T, typename C>
  48. struct to_impl<detail::CanonicalConstant<T>, C, when<
  49. hana::Constant<C>::value &&
  50. is_convertible<typename C::value_type, T>::value
  51. >>
  52. : embedding<is_embedded<typename C::value_type, T>::value>
  53. {
  54. template <typename X>
  55. static constexpr detail::canonical_constant<T, X> apply(X const&)
  56. { return {}; }
  57. };
  58. //////////////////////////////////////////////////////////////////////////
  59. // IntegralConstant (when value_type is integral)
  60. //////////////////////////////////////////////////////////////////////////
  61. template <typename T>
  62. struct IntegralConstant<detail::CanonicalConstant<T>> {
  63. static constexpr bool value = std::is_integral<T>::value;
  64. };
  65. BOOST_HANA_NAMESPACE_END
  66. #endif // !BOOST_HANA_DETAIL_CANONICAL_CONSTANT_HPP