bool.hpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*!
  2. @file
  3. Defines the `Logical` and `Comparable` models of `boost::hana::integral_constant`.
  4. Copyright Louis Dionne 2013-2022
  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_BOOL_HPP
  9. #define BOOST_HANA_BOOL_HPP
  10. #include <boost/hana/fwd/bool.hpp>
  11. #include <boost/hana/concept/integral_constant.hpp>
  12. #include <boost/hana/config.hpp>
  13. #include <boost/hana/core/to.hpp>
  14. #include <boost/hana/core/when.hpp>
  15. #include <boost/hana/detail/operators/arithmetic.hpp>
  16. #include <boost/hana/detail/operators/comparable.hpp>
  17. #include <boost/hana/detail/operators/logical.hpp>
  18. #include <boost/hana/detail/operators/orderable.hpp>
  19. #include <boost/hana/eval.hpp>
  20. #include <boost/hana/fwd/core/tag_of.hpp>
  21. #include <boost/hana/fwd/eval_if.hpp>
  22. #include <boost/hana/fwd/if.hpp>
  23. #include <boost/hana/fwd/value.hpp>
  24. #include <cstddef>
  25. #include <type_traits>
  26. #include <utility>
  27. namespace boost { namespace hana {
  28. //////////////////////////////////////////////////////////////////////////
  29. // integral_constant
  30. //////////////////////////////////////////////////////////////////////////
  31. //! @cond
  32. namespace ic_detail {
  33. template <typename T, T N, typename = std::make_integer_sequence<T, N>>
  34. struct go;
  35. template <typename T, T N, T ...i>
  36. struct go<T, N, std::integer_sequence<T, i...>> {
  37. using swallow = T[];
  38. template <typename F>
  39. static constexpr void with_index(F&& f)
  40. { (void)swallow{T{}, ((void)f(integral_constant<T, i>{}), i)...}; }
  41. template <typename F>
  42. static constexpr void without_index(F&& f)
  43. { (void)swallow{T{}, ((void)f(), i)...}; }
  44. };
  45. template <typename T, T v>
  46. template <typename F>
  47. constexpr void with_index_t<T, v>::operator()(F&& f) const
  48. { go<T, ((void)sizeof(&f), v)>::with_index(static_cast<F&&>(f)); }
  49. template <typename T, T v>
  50. template <typename F>
  51. constexpr void times_t<T, v>::operator()(F&& f) const
  52. { go<T, ((void)sizeof(&f), v)>::without_index(static_cast<F&&>(f)); }
  53. // avoid link-time error
  54. template <typename T, T v>
  55. constexpr with_index_t<T, v> times_t<T, v>::with_index;
  56. }
  57. // avoid link-time error
  58. template <typename T, T v>
  59. constexpr ic_detail::times_t<T, v> integral_constant<T, v>::times;
  60. template <typename T, T v>
  61. struct tag_of<integral_constant<T, v>> {
  62. using type = integral_constant_tag<T>;
  63. };
  64. //! @endcond
  65. //////////////////////////////////////////////////////////////////////////
  66. // Operators
  67. //////////////////////////////////////////////////////////////////////////
  68. namespace detail {
  69. template <typename T>
  70. struct comparable_operators<integral_constant_tag<T>> {
  71. static constexpr bool value = true;
  72. };
  73. template <typename T>
  74. struct orderable_operators<integral_constant_tag<T>> {
  75. static constexpr bool value = true;
  76. };
  77. template <typename T>
  78. struct arithmetic_operators<integral_constant_tag<T>> {
  79. static constexpr bool value = true;
  80. };
  81. template <typename T>
  82. struct logical_operators<integral_constant_tag<T>> {
  83. static constexpr bool value = true;
  84. };
  85. }
  86. #define BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(op) \
  87. template <typename U, U u, typename V, V v> \
  88. constexpr integral_constant<decltype(u op v), (u op v)> \
  89. operator op(integral_constant<U, u>, integral_constant<V, v>) \
  90. { return {}; } \
  91. /**/
  92. #define BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(op) \
  93. template <typename U, U u> \
  94. constexpr integral_constant<decltype(op u), (op u)> \
  95. operator op(integral_constant<U, u>) \
  96. { return {}; } \
  97. /**/
  98. // Arithmetic
  99. BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(+)
  100. // Bitwise
  101. BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(~)
  102. BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(&)
  103. BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(|)
  104. BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(^)
  105. BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(<<)
  106. BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(>>)
  107. #undef BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP
  108. #undef BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP
  109. //////////////////////////////////////////////////////////////////////////
  110. // User-defined literal
  111. //////////////////////////////////////////////////////////////////////////
  112. namespace ic_detail {
  113. constexpr int to_int(char c) {
  114. int result = 0;
  115. if (c >= 'A' && c <= 'F') {
  116. result = static_cast<int>(c) - static_cast<int>('A') + 10;
  117. }
  118. else if (c >= 'a' && c <= 'f') {
  119. result = static_cast<int>(c) - static_cast<int>('a') + 10;
  120. }
  121. else {
  122. result = static_cast<int>(c) - static_cast<int>('0');
  123. }
  124. return result;
  125. }
  126. template<std::size_t N>
  127. constexpr long long parse(const char (&arr)[N]) {
  128. long long base = 10;
  129. std::size_t offset = 0;
  130. if (N > 2) {
  131. bool starts_with_zero = arr[0] == '0';
  132. bool is_hex =
  133. starts_with_zero && (arr[1] == 'x' || arr[1] == 'X');
  134. bool is_binary = starts_with_zero && arr[1] == 'b';
  135. if (is_hex) {
  136. //0xDEADBEEF (hexadecimal)
  137. base = 16;
  138. offset = 2;
  139. }
  140. else if (is_binary) {
  141. //0b101011101 (binary)
  142. base = 2;
  143. offset = 2;
  144. }
  145. else if (starts_with_zero) {
  146. //012345 (octal)
  147. base = 8;
  148. offset = 1;
  149. }
  150. }
  151. long long number = 0;
  152. long long multiplier = 1;
  153. for (std::size_t i = 0; i < N - offset; ++i) {
  154. char c = arr[N - 1 - i];
  155. if (c != '\'') { // skip digit separators
  156. number += to_int(c) * multiplier;
  157. multiplier *= base;
  158. }
  159. }
  160. return number;
  161. }
  162. }
  163. namespace literals {
  164. template <char ...c>
  165. constexpr auto operator"" _c() {
  166. return hana::llong<ic_detail::parse<sizeof...(c)>({c...})>{};
  167. }
  168. }
  169. //////////////////////////////////////////////////////////////////////////
  170. // Model of Constant/IntegralConstant
  171. //////////////////////////////////////////////////////////////////////////
  172. template <typename T>
  173. struct IntegralConstant<integral_constant_tag<T>> {
  174. static constexpr bool value = true;
  175. };
  176. template <typename T, typename C>
  177. struct to_impl<integral_constant_tag<T>, C, when<hana::IntegralConstant<C>::value>>
  178. : embedding<is_embedded<typename C::value_type, T>::value>
  179. {
  180. template <typename N>
  181. static constexpr auto apply(N const&)
  182. { return integral_constant<T, N::value>{}; }
  183. };
  184. //////////////////////////////////////////////////////////////////////////
  185. // Optimizations
  186. //////////////////////////////////////////////////////////////////////////
  187. template <typename T>
  188. struct eval_if_impl<integral_constant_tag<T>> {
  189. template <typename Cond, typename Then, typename Else>
  190. static constexpr decltype(auto)
  191. apply(Cond const&, Then&& t, Else&& e) {
  192. constexpr bool cond = static_cast<bool>(Cond::value);
  193. return eval_if_impl::apply(hana::bool_<cond>{},
  194. static_cast<Then&&>(t),
  195. static_cast<Else&&>(e));
  196. }
  197. template <typename Then, typename Else>
  198. static constexpr decltype(auto)
  199. apply(hana::true_ const&, Then&& t, Else&&)
  200. { return hana::eval(static_cast<Then&&>(t)); }
  201. template <typename Then, typename Else>
  202. static constexpr decltype(auto)
  203. apply(hana::false_ const&, Then&&, Else&& e)
  204. { return hana::eval(static_cast<Else&&>(e)); }
  205. };
  206. template <typename T>
  207. struct if_impl<integral_constant_tag<T>> {
  208. template <typename Cond, typename Then, typename Else>
  209. static constexpr decltype(auto)
  210. apply(Cond const&, Then&& t, Else&& e) {
  211. constexpr bool cond = static_cast<bool>(Cond::value);
  212. return if_impl::apply(hana::bool_<cond>{},
  213. static_cast<Then&&>(t),
  214. static_cast<Else&&>(e));
  215. }
  216. //! @todo We could return `Then` instead of `auto` to sometimes save
  217. //! a copy, but that would break some code that would return a
  218. //! reference to a `type` object. I think the code that would be
  219. //! broken should be changed, but more thought needs to be given.
  220. template <typename Then, typename Else>
  221. static constexpr auto
  222. apply(hana::true_ const&, Then&& t, Else&&)
  223. { return static_cast<Then&&>(t); }
  224. template <typename Then, typename Else>
  225. static constexpr auto
  226. apply(hana::false_ const&, Then&&, Else&& e)
  227. { return static_cast<Else&&>(e); }
  228. };
  229. }} // end namespace boost::hana
  230. #endif // !BOOST_HANA_BOOL_HPP