bool.hpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*!
  2. @file
  3. Defines the `Logical` and `Comparable` models of `boost::hana::integral_constant`.
  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_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. BOOST_HANA_NAMESPACE_BEGIN
  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 = starts_with_zero && arr[1] == 'x';
  133. bool is_binary = starts_with_zero && arr[1] == 'b';
  134. if (is_hex) {
  135. //0xDEADBEEF (hexadecimal)
  136. base = 16;
  137. offset = 2;
  138. }
  139. else if (is_binary) {
  140. //0b101011101 (binary)
  141. base = 2;
  142. offset = 2;
  143. }
  144. else if (starts_with_zero) {
  145. //012345 (octal)
  146. base = 8;
  147. offset = 1;
  148. }
  149. }
  150. long long number = 0;
  151. long long multiplier = 1;
  152. for (std::size_t i = 0; i < N - offset; ++i) {
  153. char c = arr[N - 1 - i];
  154. if (c != '\'') { // skip digit separators
  155. number += to_int(c) * multiplier;
  156. multiplier *= base;
  157. }
  158. }
  159. return number;
  160. }
  161. }
  162. namespace literals {
  163. template <char ...c>
  164. constexpr auto operator"" _c() {
  165. return hana::llong<ic_detail::parse<sizeof...(c)>({c...})>{};
  166. }
  167. }
  168. //////////////////////////////////////////////////////////////////////////
  169. // Model of Constant/IntegralConstant
  170. //////////////////////////////////////////////////////////////////////////
  171. template <typename T>
  172. struct IntegralConstant<integral_constant_tag<T>> {
  173. static constexpr bool value = true;
  174. };
  175. template <typename T, typename C>
  176. struct to_impl<integral_constant_tag<T>, C, when<hana::IntegralConstant<C>::value>>
  177. : embedding<is_embedded<typename C::value_type, T>::value>
  178. {
  179. template <typename N>
  180. static constexpr auto apply(N const&)
  181. { return integral_constant<T, N::value>{}; }
  182. };
  183. //////////////////////////////////////////////////////////////////////////
  184. // Optimizations
  185. //////////////////////////////////////////////////////////////////////////
  186. template <typename T>
  187. struct eval_if_impl<integral_constant_tag<T>> {
  188. template <typename Cond, typename Then, typename Else>
  189. static constexpr decltype(auto)
  190. apply(Cond const&, Then&& t, Else&& e) {
  191. constexpr bool cond = static_cast<bool>(Cond::value);
  192. return eval_if_impl::apply(hana::bool_<cond>{},
  193. static_cast<Then&&>(t),
  194. static_cast<Else&&>(e));
  195. }
  196. template <typename Then, typename Else>
  197. static constexpr decltype(auto)
  198. apply(hana::true_ const&, Then&& t, Else&&)
  199. { return hana::eval(static_cast<Then&&>(t)); }
  200. template <typename Then, typename Else>
  201. static constexpr decltype(auto)
  202. apply(hana::false_ const&, Then&&, Else&& e)
  203. { return hana::eval(static_cast<Else&&>(e)); }
  204. };
  205. template <typename T>
  206. struct if_impl<integral_constant_tag<T>> {
  207. template <typename Cond, typename Then, typename Else>
  208. static constexpr decltype(auto)
  209. apply(Cond const&, Then&& t, Else&& e) {
  210. constexpr bool cond = static_cast<bool>(Cond::value);
  211. return if_impl::apply(hana::bool_<cond>{},
  212. static_cast<Then&&>(t),
  213. static_cast<Else&&>(e));
  214. }
  215. //! @todo We could return `Then` instead of `auto` to sometimes save
  216. //! a copy, but that would break some code that would return a
  217. //! reference to a `type` object. I think the code that would be
  218. //! broken should be changed, but more thought needs to be given.
  219. template <typename Then, typename Else>
  220. static constexpr auto
  221. apply(hana::true_ const&, Then&& t, Else&&)
  222. { return static_cast<Then&&>(t); }
  223. template <typename Then, typename Else>
  224. static constexpr auto
  225. apply(hana::false_ const&, Then&&, Else&& e)
  226. { return static_cast<Else&&>(e); }
  227. };
  228. BOOST_HANA_NAMESPACE_END
  229. #endif // !BOOST_HANA_BOOL_HPP