diff options
Diffstat (limited to 'boost/hana/bool.hpp')
-rw-r--r-- | boost/hana/bool.hpp | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/boost/hana/bool.hpp b/boost/hana/bool.hpp new file mode 100644 index 0000000000..e69654dd85 --- /dev/null +++ b/boost/hana/bool.hpp @@ -0,0 +1,264 @@ +/*! +@file +Defines the `Logical` and `Comparable` models of `boost::hana::integral_constant`. + +@copyright Louis Dionne 2013-2016 +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + */ + +#ifndef BOOST_HANA_BOOL_HPP +#define BOOST_HANA_BOOL_HPP + +#include <boost/hana/fwd/bool.hpp> + +#include <boost/hana/concept/integral_constant.hpp> +#include <boost/hana/config.hpp> +#include <boost/hana/core/to.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/detail/operators/arithmetic.hpp> +#include <boost/hana/detail/operators/comparable.hpp> +#include <boost/hana/detail/operators/logical.hpp> +#include <boost/hana/detail/operators/orderable.hpp> +#include <boost/hana/eval.hpp> +#include <boost/hana/fwd/core/tag_of.hpp> +#include <boost/hana/fwd/eval_if.hpp> +#include <boost/hana/fwd/if.hpp> +#include <boost/hana/fwd/value.hpp> + +#include <cstddef> +#include <type_traits> +#include <utility> + + +BOOST_HANA_NAMESPACE_BEGIN + ////////////////////////////////////////////////////////////////////////// + // integral_constant + ////////////////////////////////////////////////////////////////////////// + //! @cond + namespace ic_detail { + template <typename T, T N, typename = std::make_integer_sequence<T, N>> + struct go; + + template <typename T, T N, T ...i> + struct go<T, N, std::integer_sequence<T, i...>> { + using swallow = T[]; + + template <typename F> + static constexpr void with_index(F&& f) + { (void)swallow{T{}, ((void)f(integral_constant<T, i>{}), i)...}; } + + template <typename F> + static constexpr void without_index(F&& f) + { (void)swallow{T{}, ((void)f(), i)...}; } + }; + + template <typename T, T v> + template <typename F> + constexpr void with_index_t<T, v>::operator()(F&& f) const + { go<T, ((void)sizeof(&f), v)>::with_index(static_cast<F&&>(f)); } + + template <typename T, T v> + template <typename F> + constexpr void times_t<T, v>::operator()(F&& f) const + { go<T, ((void)sizeof(&f), v)>::without_index(static_cast<F&&>(f)); } + + // avoid link-time error + template <typename T, T v> + constexpr with_index_t<T, v> times_t<T, v>::with_index; + } + + // avoid link-time error + template <typename T, T v> + constexpr ic_detail::times_t<T, v> integral_constant<T, v>::times; + + template <typename T, T v> + struct tag_of<integral_constant<T, v>> { + using type = integral_constant_tag<T>; + }; + //! @endcond + + ////////////////////////////////////////////////////////////////////////// + // Operators + ////////////////////////////////////////////////////////////////////////// + namespace detail { + template <typename T> + struct comparable_operators<integral_constant_tag<T>> { + static constexpr bool value = true; + }; + template <typename T> + struct orderable_operators<integral_constant_tag<T>> { + static constexpr bool value = true; + }; + template <typename T> + struct arithmetic_operators<integral_constant_tag<T>> { + static constexpr bool value = true; + }; + template <typename T> + struct logical_operators<integral_constant_tag<T>> { + static constexpr bool value = true; + }; + } + +#define BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(op) \ + template <typename U, U u, typename V, V v> \ + constexpr integral_constant<decltype(u op v), (u op v)> \ + operator op(integral_constant<U, u>, integral_constant<V, v>) \ + { return {}; } \ + /**/ + +#define BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(op) \ + template <typename U, U u> \ + constexpr integral_constant<decltype(op u), (op u)> \ + operator op(integral_constant<U, u>) \ + { return {}; } \ + /**/ + + // Arithmetic + BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(+) + + // Bitwise + BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(~) + BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(&) + BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(|) + BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(^) + BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(<<) + BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(>>) + +#undef BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP +#undef BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP + + + ////////////////////////////////////////////////////////////////////////// + // User-defined literal + ////////////////////////////////////////////////////////////////////////// + namespace ic_detail { + + constexpr int to_int(char c) { + int result = 0; + + if (c >= 'A' && c <= 'F') { + result = static_cast<int>(c) - static_cast<int>('A') + 10; + } + else if (c >= 'a' && c <= 'f') { + result = static_cast<int>(c) - static_cast<int>('a') + 10; + } + else { + result = static_cast<int>(c) - static_cast<int>('0'); + } + + return result; + } + + template<std::size_t N> + constexpr long long parse(const char (&arr)[N]) { + long long base = 10; + std::size_t offset = 0; + + if (N > 2) { + bool starts_with_zero = arr[0] == '0'; + bool is_hex = starts_with_zero && arr[1] == 'x'; + bool is_binary = starts_with_zero && arr[1] == 'b'; + + if (is_hex) { + //0xDEADBEEF (hexadecimal) + base = 16; + offset = 2; + } + else if (is_binary) { + //0b101011101 (binary) + base = 2; + offset = 2; + } + else if (starts_with_zero) { + //012345 (octal) + base = 8; + offset = 1; + } + } + + long long number = 0; + long long multiplier = 1; + + for (std::size_t i = 0; i < N - offset; ++i) { + char c = arr[N - 1 - i]; + number += to_int(c) * multiplier; + multiplier *= base; + } + + return number; + } + } + + namespace literals { + template <char ...c> + constexpr auto operator"" _c() + { return llong_c<ic_detail::parse<sizeof...(c)>({c...})>; } + } + + ////////////////////////////////////////////////////////////////////////// + // Model of Constant/IntegralConstant + ////////////////////////////////////////////////////////////////////////// + template <typename T> + struct IntegralConstant<integral_constant_tag<T>> { + static constexpr bool value = true; + }; + + template <typename T, typename C> + struct to_impl<integral_constant_tag<T>, C, when<hana::IntegralConstant<C>::value>> + : embedding<is_embedded<typename C::value_type, T>::value> + { + template <typename N> + static constexpr auto apply(N const&) + { return integral_constant<T, N::value>{}; } + }; + + ////////////////////////////////////////////////////////////////////////// + // Optimizations + ////////////////////////////////////////////////////////////////////////// + template <typename T> + struct eval_if_impl<integral_constant_tag<T>> { + template <typename Cond, typename Then, typename Else> + static constexpr decltype(auto) + apply(Cond const&, Then&& t, Else&& e) { + return eval_if_impl::apply(hana::bool_c<static_cast<bool>(Cond::value)>, + static_cast<Then&&>(t), static_cast<Else&&>(e)); + } + + template <typename Then, typename Else> + static constexpr decltype(auto) + apply(hana::true_ const&, Then&& t, Else&&) + { return hana::eval(static_cast<Then&&>(t)); } + + template <typename Then, typename Else> + static constexpr decltype(auto) + apply(hana::false_ const&, Then&&, Else&& e) + { return hana::eval(static_cast<Else&&>(e)); } + }; + + template <typename T> + struct if_impl<integral_constant_tag<T>> { + template <typename Cond, typename Then, typename Else> + static constexpr decltype(auto) + apply(Cond const&, Then&& t, Else&& e) { + return if_impl::apply(hana::bool_c<static_cast<bool>(Cond::value)>, + static_cast<Then&&>(t), static_cast<Else&&>(e)); + } + + //! @todo We could return `Then` instead of `auto` to sometimes save + //! a copy, but that would break some code that would return a + //! reference to a `type` object. I think the code that would be + //! broken should be changed, but more thought needs to be given. + template <typename Then, typename Else> + static constexpr auto + apply(hana::true_ const&, Then&& t, Else&&) + { return static_cast<Then&&>(t); } + + template <typename Then, typename Else> + static constexpr auto + apply(hana::false_ const&, Then&&, Else&& e) + { return static_cast<Else&&>(e); } + }; +BOOST_HANA_NAMESPACE_END + +#endif // !BOOST_HANA_BOOL_HPP |