feat():initial version

This commit is contained in:
2026-06-09 20:16:47 +08:00
commit 85fbb3188c
14809 changed files with 3044607 additions and 0 deletions

View File

@@ -0,0 +1,186 @@
/*!
@file
Defines several `constexpr` algorithms.
@copyright Louis Dionne 2013-2017
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_DETAIL_ALGORITHM_HPP
#define BOOST_HANA_DETAIL_ALGORITHM_HPP
#include <boost/hana/functional/placeholder.hpp>
#include <boost/hana/config.hpp>
#include <cstddef>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
// Do not call this swap, otherwise it can get picked up by ADL and conflict
// with std::swap (see https://github.com/boostorg/hana/issues/297).
template <typename T>
constexpr void constexpr_swap(T& x, T& y) {
auto tmp = x;
x = y;
y = std::move(tmp);
}
template <typename BidirIter>
constexpr void reverse(BidirIter first, BidirIter last) {
while (first != last) {
if (first == --last)
break;
detail::constexpr_swap(*first, *last);
++first;
}
}
template <typename BidirIter, typename BinaryPred>
constexpr bool next_permutation(BidirIter first, BidirIter last,
BinaryPred pred)
{
BidirIter i = last;
if (first == last || first == --i)
return false;
while (true) {
BidirIter ip1 = i;
if (pred(*--i, *ip1)) {
BidirIter j = last;
while (!pred(*i, *--j))
;
detail::constexpr_swap(*i, *j);
detail::reverse(ip1, last);
return true;
}
if (i == first) {
detail::reverse(first, last);
return false;
}
}
}
template <typename BidirIter>
constexpr bool next_permutation(BidirIter first, BidirIter last)
{ return detail::next_permutation(first, last, hana::_ < hana::_); }
template <typename InputIter1, typename InputIter2, typename BinaryPred>
constexpr bool lexicographical_compare(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2,
BinaryPred pred)
{
for (; first2 != last2; ++first1, ++first2) {
if (first1 == last1 || pred(*first1, *first2))
return true;
else if (pred(*first2, *first1))
return false;
}
return false;
}
template <typename InputIter1, typename InputIter2>
constexpr bool lexicographical_compare(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2)
{ return detail::lexicographical_compare(first1, last1, first2, last2, hana::_ < hana::_); }
template <typename InputIter1, typename InputIter2, typename BinaryPred>
constexpr bool equal(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2,
BinaryPred pred)
{
for (; first1 != last1 && first2 != last2; ++first1, ++first2)
if (!pred(*first1, *first2))
return false;
return first1 == last1 && first2 == last2;
}
template <typename InputIter1, typename InputIter2>
constexpr bool equal(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2)
{ return detail::equal(first1, last1, first2, last2, hana::_ == hana::_); }
template <typename BidirIter, typename BinaryPred>
constexpr void sort(BidirIter first, BidirIter last, BinaryPred pred) {
if (first == last) return;
BidirIter i = first;
for (++i; i != last; ++i) {
BidirIter j = i;
auto t = *j;
for (BidirIter k = i; k != first && pred(t, *--k); --j)
*j = *k;
*j = t;
}
}
template <typename BidirIter>
constexpr void sort(BidirIter first, BidirIter last)
{ detail::sort(first, last, hana::_ < hana::_); }
template <typename InputIter, typename T>
constexpr InputIter find(InputIter first, InputIter last, T const& value) {
for (; first != last; ++first)
if (*first == value)
return first;
return last;
}
template <typename InputIter, typename UnaryPred>
constexpr InputIter find_if(InputIter first, InputIter last, UnaryPred pred) {
for (; first != last; ++first)
if (pred(*first))
return first;
return last;
}
template <typename ForwardIter, typename T>
constexpr void iota(ForwardIter first, ForwardIter last, T value) {
while (first != last) {
*first++ = value;
++value;
}
}
template <typename InputIt, typename T>
constexpr std::size_t
count(InputIt first, InputIt last, T const& value) {
std::size_t n = 0;
for (; first != last; ++first)
if (*first == value)
++n;
return n;
}
template <typename InputIt, typename T, typename F>
constexpr T accumulate(InputIt first, InputIt last, T init, F f) {
for (; first != last; ++first)
init = f(init, *first);
return init;
}
template <typename InputIt, typename T>
constexpr T accumulate(InputIt first, InputIt last, T init) {
return detail::accumulate(first, last, init, hana::_ + hana::_);
}
template <typename ForwardIt>
constexpr ForwardIt min_element(ForwardIt first, ForwardIt last) {
if (first == last)
return last;
ForwardIt smallest = first;
++first;
for (; first != last; ++first)
if (*first < *smallest)
smallest = first;
return smallest;
}
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_ALGORITHM_HPP

View File

@@ -0,0 +1,46 @@
/*!
@file
Defines `boost::hana::detail::any_of`.
@copyright Louis Dionne 2013-2017
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_DETAIL_ANY_OF_HPP
#define BOOST_HANA_DETAIL_ANY_OF_HPP
#include <boost/hana/config.hpp>
#include <type_traits>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
std::false_type expand(...);
template <template <typename ...> class Predicate, typename ...T>
decltype(expand(
typename std::enable_if<!Predicate<T>::value, void*>::type{}...
)) any_of_impl(int);
template <template <typename ...> class Predicate, typename ...T>
std::true_type any_of_impl(...);
//! @ingroup group-details
//! Returns whether the `Predicate` is satisfied by any of the `T...`.
//!
//! This metafunction will short-circuit the evaluation at the first
//! type satisfying the predicate, if such a type exists.
//!
//!
//! @note
//! The implementation technique used here was originally shown to
//! me by Eric Fiselier. All credits where due.
template <template <typename ...> class Predicate, typename ...T>
struct any_of
: decltype(any_of_impl<Predicate, T...>(int{}))
{ };
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_ANY_OF_HPP

View File

@@ -0,0 +1,105 @@
/*!
@file
Defines `boost::hana::detail::array`.
@copyright Louis Dionne 2013-2017
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_DETAIL_ARRAY_HPP
#define BOOST_HANA_DETAIL_ARRAY_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/algorithm.hpp>
#include <boost/hana/functional/placeholder.hpp>
#include <cstddef>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename N>
constexpr N factorial(N n) {
N result = 1;
while (n != 0)
result *= n--;
return result;
}
//! @ingroup group-details
//! A minimal `std::array` with better `constexpr` support.
//!
//! We also provide some algorithms from the `constexpr/algorithm.hpp`
//! header as member functions to make them easier to use in constexpr
//! contexts, since a `constexpr` `array` can't be mutated in place.
template <typename T, std::size_t Size>
struct array {
T elems_[Size > 0 ? Size : 1];
constexpr T& operator[](std::size_t n)
{ return elems_[n]; }
constexpr T const& operator[](std::size_t n) const
{ return elems_[n]; }
constexpr std::size_t size() const noexcept
{ return Size; }
constexpr T* begin() noexcept { return elems_; }
constexpr T const* begin() const noexcept { return elems_; }
constexpr T* end() noexcept { return elems_ + Size; }
constexpr T const* end() const noexcept { return elems_ + Size; }
// Algorithms from constexpr/algorithm.hpp
constexpr array reverse() const {
array result = *this;
detail::reverse(result.begin(), result.end());
return result;
}
template <typename BinaryPred>
constexpr auto permutations(BinaryPred pred) const {
array<array<T, Size>, detail::factorial(Size)> result{};
auto out = result.begin();
array copy = *this;
do *out++ = copy;
while (detail::next_permutation(copy.begin(), copy.end(), pred));
return result;
}
constexpr auto permutations() const
{ return this->permutations(hana::_ < hana::_); }
template <typename BinaryPred>
constexpr auto sort(BinaryPred pred) const {
array result = *this;
detail::sort(result.begin(), result.end(), pred);
return result;
}
constexpr auto sort() const
{ return this->sort(hana::_ < hana::_); }
template <typename U>
constexpr auto iota(U value) const {
array result = *this;
detail::iota(result.begin(), result.end(), value);
return result;
}
};
template <typename T, std::size_t M, typename U, std::size_t N>
constexpr bool operator==(array<T, M> a, array<U, N> b)
{ return M == N && detail::equal(a.begin(), a.end(), b.begin(), b.end()); }
template <typename T, std::size_t M, typename U, std::size_t N>
constexpr bool operator<(array<T, M> a, array<U, N> b) {
return M < N || detail::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
}
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_ARRAY_HPP

View File

@@ -0,0 +1,80 @@
/*!
@file
Defines `boost::hana::detail::CanonicalConstant`.
@copyright Louis Dionne 2013-2017
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_DETAIL_CANONICAL_CONSTANT_HPP
#define BOOST_HANA_DETAIL_CANONICAL_CONSTANT_HPP
#include <boost/hana/config.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
//! @ingroup group-details
//! Tag representing a canonical `Constant`.
//!
//! This is an implementation detail used to provide many models for
//! stuff like `Monoid`, `Group`, etc. To create a `CanonicalConstant`,
//! simply create an object with a nested `hana_tag` equal to the proper
//! specialization of `CanonicalConstant<T>`, and then also provide a
//! `constexpr` static member `::%value` holding the value of the constant.
template <typename T>
struct CanonicalConstant {
using value_type = T;
};
} BOOST_HANA_NAMESPACE_END
#include <boost/hana/concept/constant.hpp>
#include <boost/hana/concept/integral_constant.hpp>
#include <boost/hana/core/to.hpp>
#include <boost/hana/core/when.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN
//////////////////////////////////////////////////////////////////////////
// Constant
//////////////////////////////////////////////////////////////////////////
template <typename T>
struct value_impl<detail::CanonicalConstant<T>> {
template <typename X>
static constexpr decltype(auto) apply()
{ return X::value; }
};
namespace detail {
template <typename T, typename X>
struct canonical_constant {
static constexpr auto value = hana::to<T>(hana::value<X>());
using hana_tag = detail::CanonicalConstant<T>;
};
}
template <typename T, typename C>
struct to_impl<detail::CanonicalConstant<T>, C, when<
hana::Constant<C>::value &&
is_convertible<typename C::value_type, T>::value
>>
: embedding<is_embedded<typename C::value_type, T>::value>
{
template <typename X>
static constexpr detail::canonical_constant<T, X> apply(X const&)
{ return {}; }
};
//////////////////////////////////////////////////////////////////////////
// IntegralConstant (when value_type is integral)
//////////////////////////////////////////////////////////////////////////
template <typename T>
struct IntegralConstant<detail::CanonicalConstant<T>> {
static constexpr bool value = std::is_integral<T>::value;
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_CANONICAL_CONSTANT_HPP

View File

@@ -0,0 +1,78 @@
/*!
@file
Defines concepts from the Standard library.
@copyright Louis Dionne 2013-2017
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_DETAIL_CONCEPTS_HPP
#define BOOST_HANA_DETAIL_CONCEPTS_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/std_common_type.hpp>
#include <boost/hana/detail/void_t.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
//! @cond
//////////////////////////////////////////////////////////////////////////
// EqualityComparable
//////////////////////////////////////////////////////////////////////////
template <typename T, typename U = T, typename = void>
struct EqualityComparable : std::false_type { };
template <typename T>
struct EqualityComparable<T, T, detail::void_t<
decltype(static_cast<T&&>(*(T*)0) == static_cast<T&&>(*(T*)0) ? 0:0),
decltype(static_cast<T&&>(*(T*)0) != static_cast<T&&>(*(T*)0) ? 0:0)
>> : std::true_type { };
template <typename T, typename U>
struct EqualityComparable<T, U, typename std::enable_if<
!std::is_same<T, U>::value, detail::void_t<
decltype(static_cast<T&&>(*(T*)0) == static_cast<U&&>(*(U*)0) ? 0:0),
decltype(static_cast<U&&>(*(U*)0) == static_cast<T&&>(*(T*)0) ? 0:0),
decltype(static_cast<T&&>(*(T*)0) != static_cast<U&&>(*(U*)0) ? 0:0),
decltype(static_cast<U&&>(*(U*)0) != static_cast<T&&>(*(T*)0) ? 0:0),
typename detail::std_common_type<T, U>::type
>>::type> : std::integral_constant<bool,
EqualityComparable<T>::value &&
EqualityComparable<U>::value &&
EqualityComparable<typename detail::std_common_type<T, U>::type>::value
> { };
//////////////////////////////////////////////////////////////////////////
// LessThanComparable
//////////////////////////////////////////////////////////////////////////
template <typename T, typename U = T, typename = void>
struct LessThanComparable : std::false_type { };
template <typename T>
struct LessThanComparable<T, T, detail::void_t<
decltype(static_cast<T&&>(*(T*)0) < static_cast<T&&>(*(T*)0) ? 0:0)
>> : std::true_type { };
template <typename T, typename U>
struct LessThanComparable<T, U, std::enable_if_t<
!std::is_same<T, U>::value,
detail::void_t<
decltype(static_cast<T&&>(*(T*)0) < static_cast<U&&>(*(U*)0) ? 0:0),
decltype(static_cast<U&&>(*(U*)0) < static_cast<T&&>(*(T*)0) ? 0:0),
typename detail::std_common_type<T, U>::type
>
>>
: std::integral_constant<bool,
LessThanComparable<T>::value &&
LessThanComparable<U>::value &&
LessThanComparable<typename detail::std_common_type<T, U>::type>::value
>
{ };
//! @endcond
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_CONCEPTS_HPP

View File

@@ -0,0 +1,33 @@
/*!
@file
Defines `boost::hana::detail::create`.
@copyright Louis Dionne 2013-2017
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_DETAIL_CREATE_HPP
#define BOOST_HANA_DETAIL_CREATE_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
//! @ingroup group-details
//! Implementation of the generic `std::make_xxx` pattern for arbitrary
//! `xxx`s.
template <template <typename ...> class T>
struct create {
template <typename ...X>
constexpr T<typename detail::decay<X>::type...>
operator()(X&& ...x) const {
return T<typename detail::decay<X>::type...>{
static_cast<X&&>(x)...
};
}
};
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_CREATE_HPP

View File

@@ -0,0 +1,48 @@
/*!
@file
Defines a replacement for `std::decay`, which is sometimes too slow at
compile-time.
@copyright Louis Dionne 2013-2017
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_DETAIL_DECAY_HPP
#define BOOST_HANA_DETAIL_DECAY_HPP
#include <boost/hana/config.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
//! @ingroup group-details
//! Equivalent to `std::decay`, except faster.
//!
//! `std::decay` in libc++ is implemented in a suboptimal way. Since
//! this is used literally everywhere by the `make<...>` functions, it
//! is very important to keep this as efficient as possible.
//!
//! @note
//! `std::decay` is still being used in some places in the library.
//! Indeed, this is a peephole optimization and it would not be wise
//! to clutter the code with our own implementation of `std::decay`,
//! except when this actually makes a difference in compile-times.
template <typename T, typename U = typename std::remove_reference<T>::type>
struct decay {
using type = typename std::remove_cv<U>::type;
};
template <typename T, typename U>
struct decay<T, U[]> { using type = U*; };
template <typename T, typename U, std::size_t N>
struct decay<T, U[N]> { using type = U*; };
template <typename T, typename R, typename ...A>
struct decay<T, R(A...)> { using type = R(*)(A...); };
template <typename T, typename R, typename ...A>
struct decay<T, R(A..., ...)> { using type = R(*)(A..., ...); };
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_DECAY_HPP

View File

@@ -0,0 +1,56 @@
/*!
@file
Defines `BOOST_HANA_DISPATCH_IF`.
@copyright Louis Dionne 2013-2017
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_DETAIL_DISPATCH_IF_HPP
#define BOOST_HANA_DETAIL_DISPATCH_IF_HPP
#include <boost/hana/config.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN
struct deleted_implementation {
template <typename ...T>
static constexpr auto apply(T&& ...) = delete;
};
//! @ingroup group-details
//! Dispatch to the given implementation method only when a condition is
//! satisfied.
//!
//! If the condition is satisfied, this macro is equivalent to the type
//! `IMPL`. Otherwise, it is equivalent to a type with a deleted static
//! function named `apply`. When a tag-dispatching error happens, the
//! condition should be false and the deleted static function `apply`
//! will prevent the compiler from generating too much garbage.
//!
//! @note
//! When `BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS` is defined, the
//! condition is always ignored and this macro expands to the
//! implementation only.
//!
//! @remark
//! This must be implemented as a macro, because we don't want the
//! condition to be evaluated at all when
//! `BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS` is defined.
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
#define BOOST_HANA_DISPATCH_IF(IMPL, ...) \
::std::conditional_t< \
(__VA_ARGS__), \
IMPL, \
::boost::hana::deleted_implementation \
> \
/**/
#else
#define BOOST_HANA_DISPATCH_IF(IMPL, ...) IMPL
#endif
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_DISPATCH_IF_HPP

View File

@@ -0,0 +1,115 @@
/*!
@file
Defines `boost::hana::detail::ebo`.
@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_DETAIL_EBO_HPP
#define BOOST_HANA_DETAIL_EBO_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/intrinsics.hpp>
namespace _hana {
//////////////////////////////////////////////////////////////////////////
// ebo<K, V>
//
// Building block to implement the Empty Base Optimization (EBO). We
// use a short name and define it in a short namespace to reduce
// symbol lengths, since this type is used as a building block for
// other widely used types such as `hana::pair`.
//
// When available, we use compiler intrinsics to reduce the number
// of instantiations.
//
// `ebo` provides a limited set of constructors to reduce instantiations.
// Also, the constructors are open-ended and they do not check for the
// validity of their arguments, again to reduce compile-time costs.
// Users of `ebo` should make sure that they only try to construct an
// `ebo` from a compatible value.
//
// EBOs can be indexed using an arbitrary type. The recommended usage is
// to define an integrap constant wrapper for the specific container using
// EBO, and then index using that wrapper:
//
// template <int> struct idx; // wrapper for tuple
// template <typename ...T>
// struct tuple : ebo<idx<0>, T0>, ebo<idx<1>, T1>, ... { };
//
// The reason for defining one wrapper per container is to avoid any issues
// that can arise when using `ebo_get`, which casts to the base class. If
// `tuple` and `pair` are inheritting from `ebo`s with the same indexing
// scheme, trying to use `ebo_get` on a tuple of pairs will trigger an
// ambiguous base class conversion, since both tuple and pair inherit
// from `ebo`s with the same keys.
//////////////////////////////////////////////////////////////////////////
template <typename K, typename V, bool =
BOOST_HANA_TT_IS_EMPTY(V) && !BOOST_HANA_TT_IS_FINAL(V)
>
struct ebo;
// Specialize storage for empty types
template <typename K, typename V>
struct ebo<K, V, true> : V {
constexpr ebo() { }
template <typename T>
explicit constexpr ebo(T&& t)
: V(static_cast<T&&>(t))
{ }
};
// Specialize storage for non-empty types
template <typename K, typename V>
struct ebo<K, V, false> {
constexpr ebo() : data_() { }
template <typename T>
explicit constexpr ebo(T&& t)
: data_(static_cast<T&&>(t))
{ }
V data_;
};
//////////////////////////////////////////////////////////////////////////
// ebo_get
//////////////////////////////////////////////////////////////////////////
template <typename K, typename V>
constexpr V const& ebo_get(ebo<K, V, true> const& x)
{ return x; }
template <typename K, typename V>
constexpr V& ebo_get(ebo<K, V, true>& x)
{ return x; }
template <typename K, typename V>
constexpr V&& ebo_get(ebo<K, V, true>&& x)
{ return static_cast<V&&>(x); }
template <typename K, typename V>
constexpr V const& ebo_get(ebo<K, V, false> const& x)
{ return x.data_; }
template <typename K, typename V>
constexpr V& ebo_get(ebo<K, V, false>& x)
{ return x.data_; }
template <typename K, typename V>
constexpr V&& ebo_get(ebo<K, V, false>&& x)
{ return static_cast<V&&>(x.data_); }
} // end namespace _hana
BOOST_HANA_NAMESPACE_BEGIN
namespace detail {
using ::_hana::ebo;
using ::_hana::ebo_get;
}
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_EBO_HPP

View File

@@ -0,0 +1,25 @@
/*!
@file
Defines `boost::hana::detail::fast_and`.
@copyright Louis Dionne 2013-2017
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_DETAIL_FAST_AND_HPP
#define BOOST_HANA_DETAIL_FAST_AND_HPP
#include <boost/hana/config.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <bool ...b>
struct fast_and
: std::is_same<fast_and<b...>, fast_and<(b, true)...>>
{ };
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_FAST_AND_HPP

View File

@@ -0,0 +1,56 @@
/*!
@file
Defines `boost::hana::detail::first_unsatisfied_index`.
@copyright Louis Dionne 2013-2017
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_DETAIL_FIRST_UNSATISFIED_INDEX_HPP
#define BOOST_HANA_DETAIL_FIRST_UNSATISFIED_INDEX_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/value.hpp>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <bool, typename Pred, typename ...Xs>
struct find_tail_size;
template <typename Pred, typename X, typename ...Xs>
struct find_tail_size<true, Pred, X, Xs...> {
static constexpr int value = find_tail_size<
static_cast<bool>(hana::value<decltype(std::declval<Pred>()(std::declval<X>()))>()),
Pred, Xs...
>::value;
};
template <typename Pred>
struct find_tail_size<true, Pred> {
static constexpr int value = -1;
};
template <typename Pred, typename ...Xs>
struct find_tail_size<false, Pred, Xs...> {
static constexpr int value = sizeof...(Xs);
};
//! @ingroup group-details
//! Returns the index of the first element which does not satisfy `Pred`,
//! or `sizeof...(Xs)` if no such element exists.
template <typename Pred>
struct first_unsatisfied_index {
template <typename ...Xs>
constexpr auto operator()(Xs&& ...) const {
return hana::size_c<
sizeof...(Xs) - 1 - find_tail_size<true, Pred, Xs&&...>::value
>;
}
};
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_FIRST_UNSATISFIED_INDEX_HPP

View File

@@ -0,0 +1,69 @@
/*!
@file
Defines `boost::hana::detail::has_[nontrivial_]common_embedding`.
@copyright Louis Dionne 2013-2017
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_DETAIL_HAS_COMMON_EMBEDDING_HPP
#define BOOST_HANA_DETAIL_HAS_COMMON_EMBEDDING_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/common.hpp>
#include <boost/hana/core/to.hpp>
#include <boost/hana/detail/void_t.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <template <typename...> class Concept, typename T, typename U, typename = void>
struct has_common_embedding_impl : std::false_type { };
template <template <typename...> class Concept, typename T, typename U>
struct has_common_embedding_impl<Concept, T, U, detail::void_t<
typename common<T, U>::type
>> {
using Common = typename common<T, U>::type;
using type = std::integral_constant<bool,
Concept<T>::value &&
Concept<U>::value &&
Concept<Common>::value &&
is_embedded<T, Common>::value &&
is_embedded<U, Common>::value
>;
};
//! @ingroup group-details
//! Returns whether `T` and `U` both have an embedding into a
//! common type.
//!
//! If `T` and `U` do not have a common-type, this metafunction returns
//! false.
template <template <typename...> class Concept, typename T, typename U>
using has_common_embedding = typename has_common_embedding_impl<Concept, T, U>::type;
template <template <typename...> class Concept, typename T, typename U>
struct has_nontrivial_common_embedding_impl
: has_common_embedding_impl<Concept, T, U>
{ };
template <template <typename...> class Concept, typename T>
struct has_nontrivial_common_embedding_impl<Concept, T, T>
: std::false_type
{ };
//! @ingroup group-details
//! Returns whether `T` and `U` are distinct and both have an embedding
//! into a common type.
//!
//! If `T` and `U` do not have a common-type, this metafunction returns
//! false.
template <template <typename...> class Concept, typename T, typename U>
using has_nontrivial_common_embedding =
typename has_nontrivial_common_embedding_impl<Concept, T, U>::type;
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_HAS_COMMON_EMBEDDING_HPP

View File

@@ -0,0 +1,65 @@
/*!
@file
Defines `boost::hana::detail::has_duplicates`.
@copyright Louis Dionne 2013-2017
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_DETAIL_HAS_DUPLICATES_HPP
#define BOOST_HANA_DETAIL_HAS_DUPLICATES_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/fast_and.hpp>
#include <boost/hana/equal.hpp>
#include <cstddef>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename T, typename ...U>
constexpr std::size_t pack_count() {
std::size_t c = 0;
std::size_t expand[] = {0, // avoid empty array
(decltype(hana::equal(std::declval<T>(), std::declval<U>()))::value
? ++c
: c)...
};
(void)expand;
return c;
}
//! @ingroup group-details
//! Returns whether any of the `T`s are duplicate w.r.t. `hana::equal`.
//!
//! In particular, this does not check whether all of the `T`s are unique
//! as _types_, but rather whether they are unique when compared as
//! `hana::equal(std::declval<T>(), std::declval<U>())`. This assumes
//! the comparison to return an `IntegralConstant` that can be explicitly
//! converted to `bool`.
//!
//! @note
//! Since this utility is mostly used in assertions to check that there
//! are no duplicates in a sequence, we expect it to return `false` most
//! of the time (otherwise we will assert). Hence, this implementation is
//! biased towards the fact that we __will__ have to compare every pair of
//! elements in most cases, and it does not try to be lazy.
//!
//! @todo
//! This implementation is O(n^2). We could do it in O(n), but that would
//! require a more elaborate setup including storage with O(1) lookup
//! (which could be based on a compile-time hash). If we implement such
//! storage for associative sequences, we could use it to optimize this.
template <typename ...T>
struct has_duplicates {
static constexpr bool value =
sizeof...(T) > 0 &&
!detail::fast_and<(detail::pack_count<T, T...>() == 1)...>::value
;
};
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_HAS_DUPLICATES_HPP

View File

@@ -0,0 +1,145 @@
/*!
@file
Defines `boost::hana::detail::hash_table`.
@copyright Louis Dionne 2016
@copyright Jason Rice 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_DETAIL_HASH_TABLE_HPP
#define BOOST_HANA_DETAIL_HASH_TABLE_HPP
#include <boost/hana/equal.hpp>
#include <boost/hana/ext/std/integer_sequence.hpp>
#include <boost/hana/ext/std/integral_constant.hpp>
#include <boost/hana/find_if.hpp>
#include <boost/hana/fold_left.hpp>
#include <boost/hana/hash.hpp>
#include <boost/hana/optional.hpp>
#include <boost/hana/range.hpp>
#include <boost/hana/type.hpp>
#include <boost/hana/value.hpp>
#include <cstddef>
#include <type_traits>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename Hash, std::size_t ...i>
struct bucket { };
template <typename ...Buckets>
struct hash_table
: Buckets...
{ };
// find_indices:
// Returns an `index_sequence` containing possible indices for the given
// `Key` in the `Map`.
template <typename Hash, std::size_t ...i>
std::index_sequence<i...> find_indices_impl(bucket<Hash, i...> const&);
template <typename Hash>
std::index_sequence<> find_indices_impl(...);
template <typename Map, typename Key>
struct find_indices {
using Hash = typename decltype(hana::hash(std::declval<Key>()))::type;
using type = decltype(detail::find_indices_impl<Hash>(std::declval<Map>()));
};
// end find_indices
// find_index:
// Returns the actual index of a `Key` in the `Map`. The type of the key
// associated to any given index must be retrievable with the `KeyAtIndex`
// alias.
template <template <std::size_t> class KeyAtIndex, typename Key>
struct find_pred {
template <typename Index>
auto operator()(Index const&) const -> decltype(
hana::equal(std::declval<KeyAtIndex<Index::value>>(),
std::declval<Key>())
);
};
template <typename Indices, typename Key, template <std::size_t> class KeyAtIndex>
struct find_index_impl {
using type = decltype(hana::find_if(Indices{}, find_pred<KeyAtIndex, Key>{}));
};
// This is a peephole optimization for buckets that have a single entry.
// It provides a nice speedup in the at_key.number_of_lookups benchmark.
// It is perhaps possible to make this part of `find_if` itself, but we
// should make sure that we retain that speedup.
template <std::size_t i, typename Key, template <std::size_t> class KeyAtIndex>
struct find_index_impl<std::index_sequence<i>, Key, KeyAtIndex> {
using Equal = decltype(
hana::equal(std::declval<KeyAtIndex<i>>(),
std::declval<Key>())
);
using type = typename std::conditional<Equal::value,
hana::optional<std::integral_constant<std::size_t, i>>,
hana::optional<>
>::type;
};
template <typename Map, typename Key, template <std::size_t> class KeyAtIndex>
struct find_index {
using Indices = typename find_indices<Map, Key>::type;
using type = typename find_index_impl<Indices, Key, KeyAtIndex>::type;
};
// end find_index
// bucket_insert:
// Inserts the given `Index` into the bucket of the `Map` in which `Key` falls.
template <typename Bucket, typename Hash, std::size_t Index>
struct update_bucket {
using type = Bucket;
};
template <std::size_t ...i, typename Hash, std::size_t Index>
struct update_bucket<bucket<Hash, i...>, Hash, Index> {
using type = bucket<Hash, i..., Index>;
};
template <typename Map, typename Key, std::size_t Index, bool =
(find_indices<Map, Key>::type::size() > 0)
>
struct bucket_insert;
template <typename ...Buckets, typename Key, std::size_t Index>
struct bucket_insert<hash_table<Buckets...>, Key, Index, true> {
// There is a bucket for that Hash; append the new index to it.
using Hash = typename decltype(hana::hash(std::declval<Key>()))::type;
using type = hash_table<typename update_bucket<Buckets, Hash, Index>::type...>;
};
template <typename ...Buckets, typename Key, std::size_t Index>
struct bucket_insert<hash_table<Buckets...>, Key, Index, false> {
// There is no bucket for that Hash; insert a new bucket.
using Hash = typename decltype(hana::hash(std::declval<Key>()))::type;
using type = hash_table<Buckets..., bucket<Hash, Index>>;
};
// end bucket_insert
// make_hash_table:
// Creates a `hash_table` type able of holding the given number of
// elements. The type of the key associated to any given index must
// be retrievable using the `KeyAtIndex` alias. All the keys must
// be distinct and have different hashes too.
template <template <std::size_t> class KeyAtIndex, std::size_t N,
typename Indices = std::make_index_sequence<N>>
struct make_hash_table;
template <template <std::size_t> class KeyAtIndex, std::size_t N, std::size_t ...i>
struct make_hash_table<KeyAtIndex, N, std::index_sequence<i...>> {
using type = hash_table<
bucket<typename decltype(hana::hash(std::declval<KeyAtIndex<i>>()))::type, i>...
>;
};
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_HASH_TABLE_HPP

View File

@@ -0,0 +1,55 @@
/*!
@file
Defines `boost::hana::detail::index_if`.
@copyright Louis Dionne 2013-2017
@copyright Jason Rice 2017
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_DETAIL_INDEX_IF_HPP
#define BOOST_HANA_DETAIL_INDEX_IF_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/optional.hpp>
#include <cstddef>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <std::size_t i, std::size_t N, bool Done>
struct index_if_helper;
template <std::size_t i, std::size_t N>
struct index_if_helper<i, N, false> {
template <typename Pred, typename X1, typename ...Xs>
using f = typename index_if_helper<i + 1, N,
static_cast<bool>(detail::decay<decltype(
std::declval<Pred>()(std::declval<X1>()))>::type::value)
>::template f<Pred, Xs...>;
};
template <std::size_t N>
struct index_if_helper<N, N, false> {
template <typename ...>
using f = hana::optional<>;
};
template <std::size_t i, std::size_t N>
struct index_if_helper<i, N, true> {
template <typename ...>
using f = hana::optional<hana::size_t<i - 1>>;
};
template <typename Pred, typename ...Xs>
struct index_if {
using type = typename index_if_helper<0, sizeof...(Xs), false>
::template f<Pred, Xs...>;
};
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_INDEX_IF_HPP

View File

@@ -0,0 +1,249 @@
/*!
@file
Defines the barebones `boost::hana::integral_constant` template, but no
operations on it.
@copyright Louis Dionne 2013-2017
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_DETAIL_INTEGRAL_CONSTANT_HPP
#define BOOST_HANA_DETAIL_INTEGRAL_CONSTANT_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/operators/adl.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN
//! Tag representing `hana::integral_constant`.
//! @relates hana::integral_constant
template <typename T>
struct integral_constant_tag {
using value_type = T;
};
namespace ic_detail {
template <typename T, T v>
struct with_index_t {
template <typename F>
constexpr void operator()(F&& f) const;
};
template <typename T, T v>
struct times_t {
static constexpr with_index_t<T, v> with_index{};
template <typename F>
constexpr void operator()(F&& f) const;
};
}
//! @ingroup group-datatypes
//! Compile-time value of an integral type.
//!
//! An `integral_constant` is an object that represents a compile-time
//! integral value. As the name suggests, `hana::integral_constant` is
//! basically equivalent to `std::integral_constant`, except that
//! `hana::integral_constant` also provide other goodies to make them
//! easier to use, like arithmetic operators and similar features. In
//! particular, `hana::integral_constant` is guaranteed to inherit from
//! the corresponding `std::integral_constant`, and hence have the same
//! members and capabilities. The sections below explain the extensions
//! to `std::integral_constant` provided by `hana::integral_constant`.
//!
//!
//! Arithmetic operators
//! --------------------
//! `hana::integral_constant` provides arithmetic operators that return
//! `hana::integral_constant`s to ease writing compile-time arithmetic:
//! @snippet example/integral_constant.cpp operators
//!
//! It is pretty important to realize that these operators return other
//! `integral_constant`s, not normal values of an integral type.
//! Actually, all those operators work pretty much in the same way.
//! Simply put, for an operator `@`,
//! @code
//! integral_constant<T, x>{} @ integral_constant<T, y>{} == integral_constant<T, x @ y>{}
//! @endcode
//!
//! The fact that the operators return `Constant`s is very important
//! because it allows all the information that's known at compile-time
//! to be conserved as long as it's only used with other values known at
//! compile-time. It is also interesting to observe that whenever an
//! `integral_constant` is combined with a normal runtime value, the
//! result will be a runtime value (because of the implicit conversion).
//! In general, this gives us the following table
//!
//! left operand | right operand | result
//! :-----------------: | :-----------------: | :-----------------:
//! `integral_constant` | `integral_constant` | `integral_constant`
//! `integral_constant` | runtime | runtime
//! runtime | `integral_constant` | runtime
//! runtime | runtime | runtime
//!
//! The full range of provided operators is
//! - Arithmetic: binary `+`, binary `-`, `/`, `*`, `%`, unary `+`, unary `-`
//! - Bitwise: `~`, `&`, `|`, `^`, `<<`, `>>`
//! - Comparison: `==`, `!=`, `<`, `<=`, `>`, `>=`
//! - %Logical: `||`, `&&`, `!`
//!
//!
//! Construction with user-defined literals
//! ---------------------------------------
//! `integral_constant`s of type `long long` can be created with the
//! `_c` user-defined literal, which is contained in the `literals`
//! namespace:
//! @snippet example/integral_constant.cpp literals
//!
//!
//! Modeled concepts
//! ----------------
//! 1. `Constant` and `IntegralConstant`\n
//! An `integral_constant` is a model of the `IntegralConstant` concept in
//! the most obvious way possible. Specifically,
//! @code
//! integral_constant<T, v>::value == v // of type T
//! @endcode
//! The model of `Constant` follows naturally from the model of `IntegralConstant`, i.e.
//! @code
//! value<integral_constant<T, v>>() == v // of type T
//! @endcode
//!
//! 2. `Comparable`, `Orderable`, `Logical`, `Monoid`, `Group`, `Ring`, and `EuclideanRing`, `Hashable`\n
//! Those models are exactly those provided for `Constant`s, which are
//! documented in their respective concepts.
#ifdef BOOST_HANA_DOXYGEN_INVOKED
template <typename T, T v>
struct integral_constant {
//! Call a function n times.
//!
//! `times` allows a nullary function to be invoked `n` times:
//! @code
//! int_<3>::times(f)
//! @endcode
//! should be expanded by any decent compiler to
//! @code
//! f(); f(); f();
//! @endcode
//!
//! This can be useful in several contexts, e.g. for loop unrolling:
//! @snippet example/integral_constant.cpp times_loop_unrolling
//!
//! Note that `times` is really a static function object, not just a
//! static function. This allows `int_<n>::%times` to be passed to
//! higher-order algorithms:
//! @snippet example/integral_constant.cpp times_higher_order
//!
//! Also, since static members can be accessed using both the `.` and
//! the `::` syntax, one can take advantage of this (loophole?) to
//! call `times` on objects just as well as on types:
//! @snippet example/integral_constant.cpp from_object
//!
//! @note
//! `times` is equivalent to the `hana::repeat` function, which works
//! on an arbitrary `IntegralConstant`.
//!
//! Sometimes, it is also useful to know the index we're at inside the
//! function. This can be achieved by using `times.with_index`:
//! @snippet example/integral_constant.cpp times_with_index_runtime
//!
//! Remember that `times` is a _function object_, and hence it can
//! have subobjects. `with_index` is just a function object nested
//! inside `times`, which allows for this nice little interface. Also
//! note that the indices passed to the function are `integral_constant`s;
//! they are known at compile-time. Hence, we can do compile-time stuff
//! with them, like indexing inside a tuple:
//! @snippet example/integral_constant.cpp times_with_index_compile_time
//!
//! @note
//! `times.with_index(f)` guarantees that the calls to `f` will be
//! done in order of ascending index. In other words, `f` will be
//! called as `f(0)`, `f(1)`, `f(2)`, etc., but with `integral_constant`s
//! instead of normal integers. Side effects can also be done in the
//! function passed to `times` and `times.with_index`.
template <typename F>
static constexpr void times(F&& f) {
f(); f(); ... f(); // n times total
}
//! Equivalent to `hana::plus`
template <typename X, typename Y>
friend constexpr auto operator+(X&& x, Y&& y);
//! Equivalent to `hana::minus`
template <typename X, typename Y>
friend constexpr auto operator-(X&& x, Y&& y);
//! Equivalent to `hana::negate`
template <typename X>
friend constexpr auto operator-(X&& x);
//! Equivalent to `hana::mult`
template <typename X, typename Y>
friend constexpr auto operator*(X&& x, Y&& y);
//! Equivalent to `hana::div`
template <typename X, typename Y>
friend constexpr auto operator/(X&& x, Y&& y);
//! Equivalent to `hana::mod`
template <typename X, typename Y>
friend constexpr auto operator%(X&& x, Y&& y);
//! Equivalent to `hana::equal`
template <typename X, typename Y>
friend constexpr auto operator==(X&& x, Y&& y);
//! Equivalent to `hana::not_equal`
template <typename X, typename Y>
friend constexpr auto operator!=(X&& x, Y&& y);
//! Equivalent to `hana::or_`
template <typename X, typename Y>
friend constexpr auto operator||(X&& x, Y&& y);
//! Equivalent to `hana::and_`
template <typename X, typename Y>
friend constexpr auto operator&&(X&& x, Y&& y);
//! Equivalent to `hana::not_`
template <typename X>
friend constexpr auto operator!(X&& x);
//! Equivalent to `hana::less`
template <typename X, typename Y>
friend constexpr auto operator<(X&& x, Y&& y);
//! Equivalent to `hana::greater`
template <typename X, typename Y>
friend constexpr auto operator>(X&& x, Y&& y);
//! Equivalent to `hana::less_equal`
template <typename X, typename Y>
friend constexpr auto operator<=(X&& x, Y&& y);
//! Equivalent to `hana::greater_equal`
template <typename X, typename Y>
friend constexpr auto operator>=(X&& x, Y&& y);
};
#else
template <typename T, T v>
#ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
struct __declspec(empty_bases) integral_constant
#else
struct integral_constant
#endif
: std::integral_constant<T, v>
, detail::operators::adl<integral_constant<T, v>>
{
using type = integral_constant; // override std::integral_constant::type
static constexpr ic_detail::times_t<T, v> times{};
using hana_tag = integral_constant_tag<T>;
};
#endif
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_INTEGRAL_CONSTANT_HPP

View File

@@ -0,0 +1,67 @@
/*!
@file
Defines macros for commonly used type traits.
@copyright Louis Dionne 2013-2017
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_DETAIL_INTRINSICS_HPP
#define BOOST_HANA_DETAIL_INTRINSICS_HPP
#include <boost/hana/config.hpp>
// We use intrinsics if they are available because it speeds up the
// compile-times.
#if defined(BOOST_HANA_CONFIG_CLANG)
# if __has_extension(is_empty)
# define BOOST_HANA_TT_IS_EMPTY(T) __is_empty(T)
# endif
# if __has_extension(is_final)
# define BOOST_HANA_TT_IS_FINAL(T) __is_final(T)
# endif
// TODO: Right now, this intrinsic is never used directly because of
// https://llvm.org/bugs/show_bug.cgi?id=24173
# if __has_extension(is_constructible) && false
# define BOOST_HANA_TT_IS_CONSTRUCTIBLE(...) __is_constructible(__VA_ARGS__)
# endif
# if __has_extension(is_assignable)
# define BOOST_HANA_TT_IS_ASSIGNABLE(T, U) __is_assignable(T, U)
# endif
# if __has_extension(is_convertible)
# define BOOST_HANA_TT_IS_CONVERTIBLE(T, U) __is_convertible(T, U)
# endif
#endif
#if !defined(BOOST_HANA_TT_IS_EMPTY)
# include <type_traits>
# define BOOST_HANA_TT_IS_EMPTY(T) ::std::is_empty<T>::value
#endif
#if !defined(BOOST_HANA_TT_IS_FINAL)
# include <type_traits>
# define BOOST_HANA_TT_IS_FINAL(T) ::std::is_final<T>::value
#endif
#if !defined(BOOST_HANA_TT_IS_CONSTRUCTIBLE)
# include <type_traits>
# define BOOST_HANA_TT_IS_CONSTRUCTIBLE(...) ::std::is_constructible<__VA_ARGS__>::value
#endif
#if !defined(BOOST_HANA_TT_IS_ASSIGNABLE)
# include <type_traits>
# define BOOST_HANA_TT_IS_ASSIGNABLE(T, U) ::std::is_assignable<T, U>::value
#endif
#if !defined(BOOST_HANA_TT_IS_CONVERTIBLE)
# include <type_traits>
# define BOOST_HANA_TT_IS_CONVERTIBLE(T, U) ::std::is_convertible<T, U>::value
#endif
#endif // !BOOST_HANA_DETAIL_INTRINSICS_HPP

View File

@@ -0,0 +1,40 @@
/*!
@file
Defines `boost::hana::detail::nested_by`.
@copyright Louis Dionne 2013-2017
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_DETAIL_NESTED_BY_HPP
#define BOOST_HANA_DETAIL_NESTED_BY_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/nested_by_fwd.hpp>
#include <boost/hana/functional/flip.hpp>
#include <boost/hana/functional/partial.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
//! @cond
template <typename Algorithm>
template <typename Predicate, typename Object>
constexpr decltype(auto) nested_by_t<Algorithm>::
operator()(Predicate&& predicate, Object&& object) const {
return Algorithm{}(static_cast<Object&&>(object),
static_cast<Predicate&&>(predicate));
}
template <typename Algorithm>
template <typename Predicate>
constexpr decltype(auto)
nested_by_t<Algorithm>::operator()(Predicate&& predicate) const {
return hana::partial(hana::flip(Algorithm{}),
static_cast<Predicate&&>(predicate));
}
//! @endcond
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_NESTED_BY_HPP

View File

@@ -0,0 +1,55 @@
/*!
@file
Forward declares `boost::hana::detail::nested_by`.
@copyright Louis Dionne 2013-2017
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_DETAIL_NESTED_BY_FWD_HPP
#define BOOST_HANA_DETAIL_NESTED_BY_FWD_HPP
#include <boost/hana/config.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename Algorithm>
struct nested_by_t {
template <typename Predicate, typename Object>
constexpr decltype(auto)
operator()(Predicate&& predicate, Object&& object) const;
template <typename Predicate>
constexpr decltype(auto) operator()(Predicate&& predicate) const;
};
//! @ingroup group-details
//! Provides a `.by` static constexpr function object.
//!
//! When creating a binary function object of type `Algorithm` whose
//! signature is `Object x Predicate -> Return`, `nested_by<Algorithm>`
//! can be used as a base class to `Algorithm`. Doing so will provide a
//! static constexpr member called `by`, which has the two following
//! signatures:
//! @code
//! Predicate x Object -> Return
//! Predicate -> (Object -> Return)
//! @endcode
//!
//! In other words, `nested_by` is a `curry`ed and `flip`ped version of
//! `Algorithm`. Note that the function object `Algorithm` must be
//! default-constructible, since the algorithm will be called as
//! `Algorithm{}(arguments...)`.
//!
//! @note
//! This function object is especially useful because it takes care of
//! avoiding ODR violations caused by the nested static constexpr member.
template <typename Algorithm>
struct nested_by { static constexpr nested_by_t<Algorithm> by{}; };
template <typename Algorithm>
constexpr nested_by_t<Algorithm> nested_by<Algorithm>::by;
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_NESTED_BY_FWD_HPP

View File

@@ -0,0 +1,29 @@
/*!
@file
Defines `boost::hana::detail::nested_than`.
@copyright Louis Dionne 2013-2017
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_DETAIL_NESTED_THAN_HPP
#define BOOST_HANA_DETAIL_NESTED_THAN_HPP
#include <boost/hana/detail/nested_than_fwd.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/functional/flip.hpp>
#include <boost/hana/functional/partial.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
//! @cond
template <typename Algorithm>
template <typename X>
constexpr decltype(auto) nested_than_t<Algorithm>::operator()(X&& x) const
{ return hana::partial(hana::flip(Algorithm{}), static_cast<X&&>(x)); }
//! @endcond
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_NESTED_THAN_HPP

View File

@@ -0,0 +1,47 @@
/*!
@file
Forward declares `boost::hana::detail::nested_than`.
@copyright Louis Dionne 2013-2017
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_DETAIL_NESTED_THAN_FWD_HPP
#define BOOST_HANA_DETAIL_NESTED_THAN_FWD_HPP
#include <boost/hana/config.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename Algorithm>
struct nested_than_t {
template <typename X>
constexpr decltype(auto) operator()(X&& x) const;
};
//! @ingroup group-details
//! Provides a `.than` static constexpr function object.
//!
//! When creating a binary function object of type `Algo` whose signature
//! is `A x B -> Return`, `nested_than<Algo>` can be used as a base class
//! of `Algo`. Doing so will provide a static constexpr member called
//! `than`, which has the following signature:
//! @code
//! B -> A -> Return
//! @endcode
//!
//! Note that the function object `Algo` must be default-constructible,
//! since it will be called as `Algo{}(arguments...)`.
//!
//! @note
//! This function object is especially useful because it takes care of
//! avoiding ODR violations caused by the nested static constexpr member.
template <typename Algorithm>
struct nested_than { static constexpr nested_than_t<Algorithm> than{}; };
template <typename Algorithm>
constexpr nested_than_t<Algorithm> nested_than<Algorithm>::than;
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_NESTED_THAN_FWD_HPP

View File

@@ -0,0 +1,28 @@
/*!
@file
Defines `boost::hana::detail::nested_to`.
@copyright Louis Dionne 2013-2017
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_DETAIL_NESTED_TO_HPP
#define BOOST_HANA_DETAIL_NESTED_TO_HPP
#include <boost/hana/detail/nested_to_fwd.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/functional/partial.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
//! @cond
template <typename Algorithm>
template <typename X>
constexpr decltype(auto) nested_to_t<Algorithm>::operator()(X&& x) const
{ return hana::partial(Algorithm{}, static_cast<X&&>(x)); }
//! @endcond
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_NESTED_TO_HPP

View File

@@ -0,0 +1,47 @@
/*!
@file
Forward declares `boost::hana::detail::nested_to`.
@copyright Louis Dionne 2013-2017
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_DETAIL_NESTED_TO_FWD_HPP
#define BOOST_HANA_DETAIL_NESTED_TO_FWD_HPP
#include <boost/hana/config.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename Algorithm>
struct nested_to_t {
template <typename X>
constexpr decltype(auto) operator()(X&& x) const;
};
//! @ingroup group-details
//! Provides a `.to` static constexpr function object.
//!
//! When creating a binary function object of type `Algo` whose signature
//! is `Object x Object -> Return`, `nested_to<Algo>` can be used as a base
//! class of `Algo`. Doing so will provide a static constexpr member called
//! `to`, which has the following signature:
//! @code
//! Object -> Object -> Return
//! @endcode
//!
//! Note that the function object `Algo` must be default-constructible,
//! since the algorithm will be called as `Algo{}(arguments...)`.
//!
//! @note
//! This function object is especially useful because it takes care of
//! avoiding ODR violations caused by the nested static constexpr member.
template <typename Algorithm>
struct nested_to { static constexpr nested_to_t<Algorithm> to{}; };
template <typename Algorithm>
constexpr nested_to_t<Algorithm> nested_to<Algorithm>::to;
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_NESTED_TO_FWD_HPP

View File

@@ -0,0 +1,34 @@
/*!
@file
Defines `boost::hana::detail::operators::adl`.
@copyright Louis Dionne 2013-2017
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_DETAIL_OPERATORS_ADL_HPP
#define BOOST_HANA_DETAIL_OPERATORS_ADL_HPP
#include <boost/hana/config.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace operators {
//! @ingroup group-details
//! Enables [ADL](http://en.cppreference.com/w/cpp/language/adl) in the
//! `hana::detail::operators` namespace.
//!
//! This is used by containers in Hana as a quick way to automatically
//! define the operators associated to some concepts, in conjunction
//! with the `detail::xxx_operators` family of metafunctions.
//!
//! Note that `adl` can be passed template arguments to make it unique
//! amongst a set of derived classes. This allows a set of derived classes
//! not to possess a common base class, which would disable the EBO when
//! many of these derived classes are stored in a Hana container. If EBO
//! is not a concern, `adl<>` can simply be used.
template <typename ...>
struct adl { };
}} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_OPERATORS_ADL_HPP

View File

@@ -0,0 +1,78 @@
/*!
@file
Defines arithmetic operators.
@copyright Louis Dionne 2013-2017
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_DETAIL_OPERATORS_ARITHMETIC_HPP
#define BOOST_HANA_DETAIL_OPERATORS_ARITHMETIC_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/fwd/div.hpp>
#include <boost/hana/fwd/minus.hpp>
#include <boost/hana/fwd/mod.hpp>
#include <boost/hana/fwd/mult.hpp>
#include <boost/hana/fwd/negate.hpp>
#include <boost/hana/fwd/plus.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename Tag>
struct arithmetic_operators {
static constexpr bool value = false;
};
namespace operators {
template <typename X, typename Y, typename = typename std::enable_if<
detail::arithmetic_operators<typename hana::tag_of<X>::type>::value ||
detail::arithmetic_operators<typename hana::tag_of<Y>::type>::value
>::type>
constexpr auto operator+(X&& x, Y&& y)
{ return hana::plus(static_cast<X&&>(x), static_cast<Y&&>(y)); }
template <typename X, typename Y, typename = typename std::enable_if<
detail::arithmetic_operators<typename hana::tag_of<X>::type>::value ||
detail::arithmetic_operators<typename hana::tag_of<Y>::type>::value
>::type>
constexpr auto operator-(X&& x, Y&& y)
{ return hana::minus(static_cast<X&&>(x), static_cast<Y&&>(y)); }
template <typename X, typename = typename std::enable_if<
detail::arithmetic_operators<typename hana::tag_of<X>::type>::value
>::type>
constexpr auto operator-(X&& x)
{ return hana::negate(static_cast<X&&>(x)); }
template <typename X, typename Y, typename = typename std::enable_if<
detail::arithmetic_operators<typename hana::tag_of<X>::type>::value ||
detail::arithmetic_operators<typename hana::tag_of<Y>::type>::value
>::type>
constexpr auto operator*(X&& x, Y&& y)
{ return hana::mult(static_cast<X&&>(x), static_cast<Y&&>(y)); }
template <typename X, typename Y, typename = typename std::enable_if<
detail::arithmetic_operators<typename hana::tag_of<X>::type>::value ||
detail::arithmetic_operators<typename hana::tag_of<Y>::type>::value
>::type>
constexpr auto operator/(X&& x, Y&& y)
{ return hana::div(static_cast<X&&>(x), static_cast<Y&&>(y)); }
template <typename X, typename Y, typename = typename std::enable_if<
detail::arithmetic_operators<typename hana::tag_of<X>::type>::value ||
detail::arithmetic_operators<typename hana::tag_of<Y>::type>::value
>::type>
constexpr auto operator%(X&& x, Y&& y)
{ return hana::mod(static_cast<X&&>(x), static_cast<Y&&>(y)); }
} // end namespace operators
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_OPERATORS_ARITHMETIC_HPP

View File

@@ -0,0 +1,52 @@
/*!
@file
Defines operators for Comparables.
@copyright Louis Dionne 2013-2017
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_DETAIL_OPERATORS_COMPARABLE_HPP
#define BOOST_HANA_DETAIL_OPERATORS_COMPARABLE_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/fwd/equal.hpp>
#include <boost/hana/fwd/not_equal.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename Tag>
struct comparable_operators {
static constexpr bool value = false;
};
namespace operators {
template <typename X, typename Y, typename = typename std::enable_if<
!detail::has_idempotent_tag<X>::value &&
!detail::has_idempotent_tag<Y>::value &&
(detail::comparable_operators<
typename hana::tag_of<X>::type>::value ||
detail::comparable_operators<
typename hana::tag_of<Y>::type>::value)
>::type>
constexpr auto operator==(X&& x, Y&& y)
{ return hana::equal(static_cast<X&&>(x), static_cast<Y&&>(y)); }
template <typename X, typename Y, typename = typename std::enable_if<
!detail::has_idempotent_tag<X>::value &&
!detail::has_idempotent_tag<Y>::value &&
(detail::comparable_operators<
typename hana::tag_of<X>::type>::value ||
detail::comparable_operators<
typename hana::tag_of<Y>::type>::value)
>::type>
constexpr auto operator!=(X&& x, Y&& y)
{ return hana::not_equal(static_cast<X&&>(x), static_cast<Y&&>(y)); }
} // end namespace operators
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_OPERATORS_COMPARABLE_HPP

View File

@@ -0,0 +1,40 @@
/*!
@file
Defines operators for Iterables.
@copyright Louis Dionne 2013-2017
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_DETAIL_OPERATORS_ITERABLE_HPP
#define BOOST_HANA_DETAIL_OPERATORS_ITERABLE_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/fwd/at.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename Derived>
struct iterable_operators {
template <typename N>
constexpr decltype(auto) operator[](N&& n) & {
return hana::at(static_cast<Derived&>(*this),
static_cast<N&&>(n));
}
template <typename N>
constexpr decltype(auto) operator[](N&& n) const& {
return hana::at(static_cast<Derived const&>(*this),
static_cast<N&&>(n));
}
template <typename N>
constexpr decltype(auto) operator[](N&& n) && {
return hana::at(static_cast<Derived&&>(*this),
static_cast<N&&>(n));
}
};
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_OPERATORS_ITERABLE_HPP

View File

@@ -0,0 +1,51 @@
/*!
@file
Defines logical operators.
@copyright Louis Dionne 2013-2017
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_DETAIL_OPERATORS_LOGICAL_HPP
#define BOOST_HANA_DETAIL_OPERATORS_LOGICAL_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/fwd/and.hpp>
#include <boost/hana/fwd/not.hpp>
#include <boost/hana/fwd/or.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename Tag>
struct logical_operators {
static constexpr bool value = false;
};
namespace operators {
template <typename X, typename Y, typename = typename std::enable_if<
detail::logical_operators<typename hana::tag_of<X>::type>::value ||
detail::logical_operators<typename hana::tag_of<Y>::type>::value
>::type>
constexpr auto operator||(X&& x, Y&& y)
{ return hana::or_(static_cast<X&&>(x), static_cast<Y&&>(y)); }
template <typename X, typename Y, typename = typename std::enable_if<
detail::logical_operators<typename hana::tag_of<X>::type>::value ||
detail::logical_operators<typename hana::tag_of<Y>::type>::value
>::type>
constexpr auto operator&&(X&& x, Y&& y)
{ return hana::and_(static_cast<X&&>(x), static_cast<Y&&>(y)); }
template <typename X, typename = typename std::enable_if<
detail::logical_operators<typename hana::tag_of<X>::type>::value
>::type>
constexpr auto operator!(X&& x)
{ return hana::not_(static_cast<X&&>(x)); }
} // end namespace operators
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_OPERATORS_LOGICAL_HPP

View File

@@ -0,0 +1,35 @@
/*!
@file
Defines operators for Monads.
@copyright Louis Dionne 2013-2017
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_DETAIL_OPERATORS_MONAD_HPP
#define BOOST_HANA_DETAIL_OPERATORS_MONAD_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/fwd/chain.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename Tag>
struct monad_operators {
static constexpr bool value = false;
};
namespace operators {
template <typename Xs, typename F, typename = typename std::enable_if<
detail::monad_operators<typename hana::tag_of<Xs>::type>::value
>::type>
constexpr auto operator|(Xs&& xs, F&& f)
{ return hana::chain(static_cast<Xs&&>(xs), static_cast<F&&>(f)); }
} // end namespace operators
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_OPERATORS_MONAD_HPP

View File

@@ -0,0 +1,60 @@
/*!
@file
Defines operators for Orderables.
@copyright Louis Dionne 2013-2017
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_DETAIL_OPERATORS_ORDERABLE_HPP
#define BOOST_HANA_DETAIL_OPERATORS_ORDERABLE_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/fwd/greater.hpp>
#include <boost/hana/fwd/greater_equal.hpp>
#include <boost/hana/fwd/less.hpp>
#include <boost/hana/fwd/less_equal.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename Tag>
struct orderable_operators {
static constexpr bool value = false;
};
namespace operators {
template <typename X, typename Y, typename = typename std::enable_if<
detail::orderable_operators<typename hana::tag_of<X>::type>::value ||
detail::orderable_operators<typename hana::tag_of<Y>::type>::value
>::type>
constexpr auto operator<(X&& x, Y&& y)
{ return hana::less(static_cast<X&&>(x), static_cast<Y&&>(y)); }
template <typename X, typename Y, typename = typename std::enable_if<
detail::orderable_operators<typename hana::tag_of<X>::type>::value ||
detail::orderable_operators<typename hana::tag_of<Y>::type>::value
>::type>
constexpr auto operator>(X&& x, Y&& y)
{ return hana::greater(static_cast<X&&>(x), static_cast<Y&&>(y)); }
template <typename X, typename Y, typename = typename std::enable_if<
detail::orderable_operators<typename hana::tag_of<X>::type>::value ||
detail::orderable_operators<typename hana::tag_of<Y>::type>::value
>::type>
constexpr auto operator<=(X&& x, Y&& y)
{ return hana::less_equal(static_cast<X&&>(x), static_cast<Y&&>(y)); }
template <typename X, typename Y, typename = typename std::enable_if<
detail::orderable_operators<typename hana::tag_of<X>::type>::value ||
detail::orderable_operators<typename hana::tag_of<Y>::type>::value
>::type>
constexpr auto operator>=(X&& x, Y&& y)
{ return hana::greater_equal(static_cast<X&&>(x), static_cast<Y&&>(y)); }
} // end namespace operators
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_OPERATORS_ORDERABLE_HPP

View File

@@ -0,0 +1,40 @@
/*!
@file
Defines operators for Searchables.
@copyright Louis Dionne 2013-2017
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_DETAIL_OPERATORS_SEARCHABLE_HPP
#define BOOST_HANA_DETAIL_OPERATORS_SEARCHABLE_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/fwd/at_key.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename Derived>
struct searchable_operators {
template <typename Key>
constexpr decltype(auto) operator[](Key&& key) & {
return hana::at_key(static_cast<Derived&>(*this),
static_cast<Key&&>(key));
}
template <typename Key>
constexpr decltype(auto) operator[](Key&& key) && {
return hana::at_key(static_cast<Derived&&>(*this),
static_cast<Key&&>(key));
}
template <typename Key>
constexpr decltype(auto) operator[](Key&& key) const& {
return hana::at_key(static_cast<Derived const&>(*this),
static_cast<Key&&>(key));
}
};
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_OPERATORS_SEARCHABLE_HPP

View File

@@ -0,0 +1,39 @@
/*!
@file
Defines generally useful preprocessor macros.
@copyright Louis Dionne 2013-2017
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_DETAIL_PREPROCESSOR_HPP
#define BOOST_HANA_DETAIL_PREPROCESSOR_HPP
//! @ingroup group-details
//! Expands to the concatenation of its two arguments.
#define BOOST_HANA_PP_CONCAT(x, y) BOOST_HANA_PP_CONCAT_PRIMITIVE(x, y)
#define BOOST_HANA_PP_CONCAT_PRIMITIVE(x, y) x ## y
//! @ingroup group-details
//! Expands to the stringized version of its argument.
#define BOOST_HANA_PP_STRINGIZE(...) BOOST_HANA_PP_STRINGIZE_PRIMITIVE(__VA_ARGS__)
#define BOOST_HANA_PP_STRINGIZE_PRIMITIVE(...) #__VA_ARGS__
//! @ingroup group-details
//! Expands to its first argument.
#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
#define BOOST_HANA_PP_FRONT(...) BOOST_HANA_PP_FRONT_IMPL_I(__VA_ARGS__)
#define BOOST_HANA_PP_FRONT_IMPL_I(...) BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_FRONT_IMPL(__VA_ARGS__, ),)
#else
#define BOOST_HANA_PP_FRONT(...) BOOST_HANA_PP_FRONT_IMPL(__VA_ARGS__, )
#endif
#define BOOST_HANA_PP_FRONT_IMPL(e0, ...) e0
//! @ingroup group-details
//! Expands to all of its arguments, except for the first one.
//!
//! This macro may not be called with less than 2 arguments.
#define BOOST_HANA_PP_DROP_FRONT(e0, ...) __VA_ARGS__
#endif // !BOOST_HANA_DETAIL_PREPROCESSOR_HPP

View File

@@ -0,0 +1,36 @@
/*!
@file
Defines a SFINAE-friendly version of `std::common_type`.
@copyright Louis Dionne 2013-2017
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_DETAIL_STD_COMMON_TYPE_HPP
#define BOOST_HANA_DETAIL_STD_COMMON_TYPE_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
//! @ingroup group-details
//! Equivalent to `std::common_type`, except it is SFINAE-friendly and
//! does not support custom specializations.
template <typename T, typename U, typename = void>
struct std_common_type { };
template <typename T, typename U>
struct std_common_type<T, U, decltype((void)(
true ? std::declval<T>() : std::declval<U>()
))> {
using type = typename detail::decay<
decltype(true ? std::declval<T>() : std::declval<U>())
>::type;
};
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_STD_COMMON_TYPE_HPP

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,57 @@
/*!
@file
Defines `boost::hana::detail::type_at`.
@copyright Louis Dionne 2013-2017
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_DETAIL_TYPE_AT_HPP
#define BOOST_HANA_DETAIL_TYPE_AT_HPP
#include <boost/hana/config.hpp>
#include <cstddef>
#include <utility>
// If possible, use an intrinsic provided by Clang
#if defined(__has_builtin)
# if __has_builtin(__type_pack_element)
# define BOOST_HANA_USE_TYPE_PACK_ELEMENT_INTRINSIC
# endif
#endif
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
namespace td {
template <std::size_t I, typename T>
struct elt { using type = T; };
template <typename Indices, typename ...T>
struct indexer;
template <std::size_t ...I, typename ...T>
struct indexer<std::index_sequence<I...>, T...>
: elt<I, T>...
{ };
template <std::size_t I, typename T>
elt<I, T> get_elt(elt<I, T> const&);
}
//! @ingroup group-details
//! Classic MPL-style metafunction returning the nth element of a type
//! parameter pack.
template <std::size_t n, typename ...T>
struct type_at {
#if defined(BOOST_HANA_USE_TYPE_PACK_ELEMENT_INTRINSIC)
using type = __type_pack_element<n, T...>;
#else
using Indexer = td::indexer<std::make_index_sequence<sizeof...(T)>, T...>;
using type = typename decltype(td::get_elt<n>(Indexer{}))::type;
#endif
};
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_TYPE_AT_HPP

View File

@@ -0,0 +1,145 @@
/*!
@file
Defines `boost::hana::detail::type_foldl1`.
@copyright Louis Dionne 2013-2017
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_DETAIL_TYPE_FOLDL1_HPP
#define BOOST_HANA_DETAIL_TYPE_FOLDL1_HPP
#include <boost/hana/config.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <unsigned n>
struct type_foldl1_t;
template <>
struct type_foldl1_t<0> {
template <
template <typename ...> class f,
typename state
>
using result = state;
};
template <>
struct type_foldl1_t<1> {
template <
template <typename ...> class f,
typename state,
typename x1
>
using result = typename f<state, x1>::type;
};
template <>
struct type_foldl1_t<2> {
template <
template <typename ...> class f,
typename state,
typename x1, typename x2
>
using result = typename f<typename f<state, x1>::type, x2>::type;
};
template <>
struct type_foldl1_t<3> {
template <
template <typename ...> class f,
typename state,
typename x1, typename x2, typename x3
>
using result = typename f<
typename f<
typename f<state, x1>::type,
x2
>::type,
x3
>::type;
};
template <>
struct type_foldl1_t<4> {
template <
template <typename ...> class f,
typename state,
typename x1, typename x2, typename x3, typename x4
>
using result = typename f<
typename f<
typename f<
typename f<state, x1>::type,
x2
>::type,
x3
>::type,
x4
>::type;
};
template <>
struct type_foldl1_t<5> {
template <
template <typename ...> class f,
typename state,
typename x1, typename x2, typename x3, typename x4, typename x5
>
using result = typename f<
typename f<
typename f<
typename f<
typename f<state, x1>::type,
x2
>::type,
x3
>::type,
x4
>::type,
x5
>::type;
};
template <>
struct type_foldl1_t<6> {
template <
template <typename ...> class f,
typename state,
typename x1, typename x2, typename x3, typename x4, typename x5, typename x6,
typename ...xs
>
using result =
typename type_foldl1_t<(sizeof...(xs) > 6 ? 6 : sizeof...(xs))>::
template result<
f,
typename f<
typename f<
typename f<
typename f<
typename f<
typename f<state, x1>::type,
x2
>::type,
x3
>::type,
x4
>::type,
x5
>::type,
x6
>::type,
xs...
>;
};
template <template <typename ...> class f, typename x1, typename ...xn>
struct type_foldl1 {
using type = typename type_foldl1_t<(sizeof...(xn) > 6 ? 6 : sizeof...(xn))>
::template result<f, x1, xn...>;
};
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_TYPE_FOLDL1_HPP

View File

@@ -0,0 +1,149 @@
/*!
@file
Defines `boost::hana::detail::type_foldr1`.
@copyright Louis Dionne 2013-2017
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_DETAIL_TYPE_FOLDR1_HPP
#define BOOST_HANA_DETAIL_TYPE_FOLDR1_HPP
#include <boost/hana/config.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <unsigned n>
struct type_foldr1_t;
template <>
struct type_foldr1_t<0> {
template <
template <typename ...> class f,
typename state
>
using result = state;
};
template <>
struct type_foldr1_t<1> {
template <
template <typename ...> class f,
typename x1,
typename state
>
using result = typename f<x1, state>::type;
};
template <>
struct type_foldr1_t<2> {
template <
template <typename ...> class f,
typename x1, typename x2,
typename state
>
using result = typename f<x1, typename f<x2, state>::type>::type;
};
template <>
struct type_foldr1_t<3> {
template <
template <typename ...> class f,
typename x1, typename x2, typename x3,
typename state
>
using result = typename f<
x1,
typename f<
x2,
typename f<
x3,
state
>::type
>::type
>::type;
};
template <>
struct type_foldr1_t<4> {
template <
template <typename ...> class f,
typename x1, typename x2, typename x3, typename x4,
typename state
>
using result = typename f<
x1,
typename f<
x2,
typename f<
x3,
typename f<
x4,
state
>::type
>::type
>::type
>::type;
};
template <>
struct type_foldr1_t<5> {
template <
template <typename ...> class f,
typename x1, typename x2, typename x3, typename x4, typename x5,
typename state
>
using result = typename f<
x1,
typename f<
x2,
typename f<
x3,
typename f<
x4,
typename f<
x5,
state
>::type
>::type
>::type
>::type
>::type;
};
template <>
struct type_foldr1_t<6> {
template <
template <typename ...> class f,
typename x1, typename x2, typename x3, typename x4, typename x5, typename x6,
typename ...xs
>
using result =
typename f<
x1,
typename f<
x2,
typename f<
x3,
typename f<
x4,
typename f<
x5,
typename type_foldr1_t<(sizeof...(xs) > 6 ? 6 : sizeof...(xs))>::
template result<f, x6, xs...>
>::type
>::type
>::type
>::type
>::type;
};
template <template <typename ...> class f, typename x1, typename ...xn>
struct type_foldr1 {
using type = typename type_foldr1_t<(sizeof...(xn) > 6 ? 6 : sizeof...(xn))>
::template result<f, x1, xn...>;
};
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_TYPE_FOLDR1_HPP

View File

@@ -0,0 +1,70 @@
/*!
@file
Defines `boost::hana::detail::unpack_flatten`.
@copyright Louis Dionne 2013-2017
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_DETAIL_UNPACK_FLATTEN_HPP
#define BOOST_HANA_DETAIL_UNPACK_FLATTEN_HPP
#include <boost/hana/at.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/algorithm.hpp>
#include <boost/hana/detail/array.hpp>
#include <boost/hana/length.hpp>
#include <boost/hana/unpack.hpp>
#include <cstddef>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <std::size_t ...Lengths>
struct flatten_indices {
// avoid empty arrays by appending 0 to `lengths`
static constexpr std::size_t lengths[sizeof...(Lengths) + 1] = {Lengths..., 0};
static constexpr auto flat_length =
detail::accumulate(lengths, lengths + sizeof...(Lengths), 0);
template <bool Inner>
static constexpr auto compute() {
detail::array<std::size_t, flat_length> indices{};
for (std::size_t index = 0, i = 0; i < sizeof...(Lengths); ++i)
for (std::size_t j = 0; j < lengths[i]; ++j, ++index)
indices[index] = (Inner ? i : j);
return indices;
}
static constexpr auto inner = compute<true>();
static constexpr auto outer = compute<false>();
template <typename Xs, typename F, std::size_t ...i>
static constexpr decltype(auto)
apply(Xs&& xs, F&& f, std::index_sequence<i...>) {
return static_cast<F&&>(f)(
hana::at_c<outer[i]>(hana::at_c<inner[i]>(
static_cast<Xs&&>(xs)
))...
);
}
};
struct make_flatten_indices {
template <typename ...Xs>
auto operator()(Xs const& ...xs) const -> detail::flatten_indices<
decltype(hana::length(xs))::value...
>;
};
template <typename Xs, typename F>
constexpr decltype(auto) unpack_flatten(Xs&& xs, F&& f) {
using Indices = decltype(hana::unpack(xs, make_flatten_indices{}));
return Indices::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f),
std::make_index_sequence<Indices::flat_length>{});
}
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_UNPACK_FLATTEN_HPP

View File

@@ -0,0 +1,40 @@
/*!
@file
Defines `boost::hana::detail::variadic::at`.
@copyright Louis Dionne 2013-2017
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_DETAIL_VARIADIC_AT_HPP
#define BOOST_HANA_DETAIL_VARIADIC_AT_HPP
#include <boost/hana/config.hpp>
#include <cstddef>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
template <std::size_t n, typename = std::make_index_sequence<n>>
struct at_type;
template <std::size_t n, std::size_t ...ignore>
struct at_type<n, std::index_sequence<ignore...>> {
private:
template <typename Nth>
static constexpr auto go(decltype(ignore, (void*)0)..., Nth nth, ...)
{ return nth; }
public:
template <typename ...Xs>
constexpr auto operator()(Xs ...xs) const
{ return *go(&xs...); }
};
template <std::size_t n>
constexpr at_type<n> at{};
}} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_VARIADIC_AT_HPP

View File

@@ -0,0 +1,47 @@
/*!
@file
Defines `boost::hana::detail::variadic::drop_into`.
@copyright Louis Dionne 2013-2017
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_DETAIL_VARIADIC_DROP_INTO_HPP
#define BOOST_HANA_DETAIL_VARIADIC_DROP_INTO_HPP
#include <boost/hana/config.hpp>
#include <cstddef>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
template <std::size_t n, typename F, typename = std::make_index_sequence<n>>
struct dropper;
template <std::size_t n, typename F, std::size_t ...ignore>
struct dropper<n, F, std::index_sequence<ignore...>> {
F f;
template <typename ...Rest>
constexpr auto go(decltype(ignore, (void*)0)..., Rest ...rest) const
{ return f(*rest...); }
template <typename ...Xs>
constexpr auto operator()(Xs ...xs) const
{ return go(&xs...); }
};
template <std::size_t n>
struct make_dropper {
template <typename F>
constexpr auto operator()(F f) const
{ return dropper<n, decltype(f)>{f}; }
};
template <std::size_t n>
constexpr make_dropper<n> drop_into{};
}} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_VARIADIC_DROP_INTO_HPP

View File

@@ -0,0 +1,214 @@
/*!
@file
Defines `boost::hana::detail::variadic::foldl1`.
@copyright Louis Dionne 2013-2017
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_DETAIL_VARIADIC_FOLDL1_HPP
#define BOOST_HANA_DETAIL_VARIADIC_FOLDL1_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
//! @cond
template <unsigned int n, typename = when<true>>
struct foldl1_impl;
template <>
struct foldl1_impl<1> {
template <typename F, typename X1>
static constexpr X1 apply(F&&, X1&& x1)
{ return static_cast<X1&&>(x1); }
};
template <>
struct foldl1_impl<2> {
template <typename F, typename X1, typename X2>
static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2) {
return static_cast<F&&>(f)(static_cast<X1&&>(x1),
static_cast<X2&&>(x2));
}
};
template <>
struct foldl1_impl<3> {
template <typename F, typename X1, typename X2, typename X3>
static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3) {
return f(f(static_cast<X1&&>(x1),
static_cast<X2&&>(x2)),
static_cast<X3&&>(x3));
}
};
template <>
struct foldl1_impl<4> {
template <typename F, typename X1, typename X2, typename X3, typename X4>
static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4) {
return f(f(f(static_cast<X1&&>(x1),
static_cast<X2&&>(x2)),
static_cast<X3&&>(x3)),
static_cast<X4&&>(x4));
}
};
template <>
struct foldl1_impl<5> {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5>
static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5) {
return f(f(f(f(static_cast<X1&&>(x1),
static_cast<X2&&>(x2)),
static_cast<X3&&>(x3)),
static_cast<X4&&>(x4)),
static_cast<X5&&>(x5));
}
};
template <>
struct foldl1_impl<6> {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6>
static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6) {
return f(f(f(f(f(static_cast<X1&&>(x1),
static_cast<X2&&>(x2)),
static_cast<X3&&>(x3)),
static_cast<X4&&>(x4)),
static_cast<X5&&>(x5)),
static_cast<X6&&>(x6));
}
};
template <unsigned int n>
struct foldl1_impl<n, when<(n >= 7) && (n < 14)>> {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename ...Xn>
static constexpr decltype(auto)
apply(F&& f
, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
, Xn&& ...xn)
{
return foldl1_impl<sizeof...(xn) + 1>::apply(
f,
f(f(f(f(f(f(static_cast<X1&&>(x1),
static_cast<X2&&>(x2)),
static_cast<X3&&>(x3)),
static_cast<X4&&>(x4)),
static_cast<X5&&>(x5)),
static_cast<X6&&>(x6)),
static_cast<X7&&>(x7)),
static_cast<Xn&&>(xn)...
);
}
};
template <unsigned int n>
struct foldl1_impl<n, when<(n >= 14) && (n < 28)>> {
template <
typename F
, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7
, typename X8, typename X9, typename X10, typename X11, typename X12, typename X13, typename X14
, typename ...Xn
>
static constexpr decltype(auto)
apply(F&& f
, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
, X8&& x8, X9&& x9, X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14
, Xn&& ...xn)
{
return foldl1_impl<sizeof...(xn) + 1>::apply(
f,
f(f(f(f(f(f(f(f(f(f(f(f(f(
static_cast<X1&&>(x1), static_cast<X2&&>(x2)), static_cast<X3&&>(x3)), static_cast<X4&&>(x4)), static_cast<X5&&>(x5)), static_cast<X6&&>(x6)), static_cast<X7&&>(x7)),
static_cast<X8&&>(x8)), static_cast<X9&&>(x9)), static_cast<X10&&>(x10)), static_cast<X11&&>(x11)), static_cast<X12&&>(x12)), static_cast<X13&&>(x13)), static_cast<X14&&>(x14))
, static_cast<Xn&&>(xn)...);
}
};
template <unsigned int n>
struct foldl1_impl<n, when<(n >= 28) && (n < 56)>> {
template <
typename F
, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7
, typename X8, typename X9, typename X10, typename X11, typename X12, typename X13, typename X14
, typename X15, typename X16, typename X17, typename X18, typename X19, typename X20, typename X21
, typename X22, typename X23, typename X24, typename X25, typename X26, typename X27, typename X28
, typename ...Xn
>
static constexpr decltype(auto)
apply(F&& f
, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
, X8&& x8, X9&& x9, X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14
, X15&& x15, X16&& x16, X17&& x17, X18&& x18, X19&& x19, X20&& x20, X21&& x21
, X22&& x22, X23&& x23, X24&& x24, X25&& x25, X26&& x26, X27&& x27, X28&& x28
, Xn&& ...xn)
{
return foldl1_impl<sizeof...(xn) + 1>::apply(
f,
f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(
static_cast<X1&&>(x1), static_cast<X2&&>(x2)), static_cast<X3&&>(x3)), static_cast<X4&&>(x4)), static_cast<X5&&>(x5)), static_cast<X6&&>(x6)), static_cast<X7&&>(x7)),
static_cast<X8&&>(x8)), static_cast<X9&&>(x9)), static_cast<X10&&>(x10)), static_cast<X11&&>(x11)), static_cast<X12&&>(x12)), static_cast<X13&&>(x13)), static_cast<X14&&>(x14)),
static_cast<X15&&>(x15)), static_cast<X16&&>(x16)), static_cast<X17&&>(x17)), static_cast<X18&&>(x18)), static_cast<X19&&>(x19)), static_cast<X20&&>(x20)), static_cast<X21&&>(x21)),
static_cast<X22&&>(x22)), static_cast<X23&&>(x23)), static_cast<X24&&>(x24)), static_cast<X25&&>(x25)), static_cast<X26&&>(x26)), static_cast<X27&&>(x27)), static_cast<X28&&>(x28))
, static_cast<Xn&&>(xn)...);
}
};
template <unsigned int n>
struct foldl1_impl<n, when<(n >= 56)>> {
template <
typename F
, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7
, typename X8, typename X9, typename X10, typename X11, typename X12, typename X13, typename X14
, typename X15, typename X16, typename X17, typename X18, typename X19, typename X20, typename X21
, typename X22, typename X23, typename X24, typename X25, typename X26, typename X27, typename X28
, typename X29, typename X30, typename X31, typename X32, typename X33, typename X34, typename X35
, typename X36, typename X37, typename X38, typename X39, typename X40, typename X41, typename X42
, typename X43, typename X44, typename X45, typename X46, typename X47, typename X48, typename X49
, typename X50, typename X51, typename X52, typename X53, typename X54, typename X55, typename X56
, typename ...Xn
>
static constexpr decltype(auto)
apply(F&& f
, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
, X8&& x8, X9&& x9, X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14
, X15&& x15, X16&& x16, X17&& x17, X18&& x18, X19&& x19, X20&& x20, X21&& x21
, X22&& x22, X23&& x23, X24&& x24, X25&& x25, X26&& x26, X27&& x27, X28&& x28
, X29&& x29, X30&& x30, X31&& x31, X32&& x32, X33&& x33, X34&& x34, X35&& x35
, X36&& x36, X37&& x37, X38&& x38, X39&& x39, X40&& x40, X41&& x41, X42&& x42
, X43&& x43, X44&& x44, X45&& x45, X46&& x46, X47&& x47, X48&& x48, X49&& x49
, X50&& x50, X51&& x51, X52&& x52, X53&& x53, X54&& x54, X55&& x55, X56&& x56
, Xn&& ...xn)
{
return foldl1_impl<sizeof...(xn) + 1>::apply(
f,
f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(
static_cast<X1&&>(x1), static_cast<X2&&>(x2)), static_cast<X3&&>(x3)), static_cast<X4&&>(x4)), static_cast<X5&&>(x5)), static_cast<X6&&>(x6)), static_cast<X7&&>(x7)),
static_cast<X8&&>(x8)), static_cast<X9&&>(x9)), static_cast<X10&&>(x10)), static_cast<X11&&>(x11)), static_cast<X12&&>(x12)), static_cast<X13&&>(x13)), static_cast<X14&&>(x14)),
static_cast<X15&&>(x15)), static_cast<X16&&>(x16)), static_cast<X17&&>(x17)), static_cast<X18&&>(x18)), static_cast<X19&&>(x19)), static_cast<X20&&>(x20)), static_cast<X21&&>(x21)),
static_cast<X22&&>(x22)), static_cast<X23&&>(x23)), static_cast<X24&&>(x24)), static_cast<X25&&>(x25)), static_cast<X26&&>(x26)), static_cast<X27&&>(x27)), static_cast<X28&&>(x28)),
static_cast<X29&&>(x29)), static_cast<X30&&>(x30)), static_cast<X31&&>(x31)), static_cast<X32&&>(x32)), static_cast<X33&&>(x33)), static_cast<X34&&>(x34)), static_cast<X35&&>(x35)),
static_cast<X36&&>(x36)), static_cast<X37&&>(x37)), static_cast<X38&&>(x38)), static_cast<X39&&>(x39)), static_cast<X40&&>(x40)), static_cast<X41&&>(x41)), static_cast<X42&&>(x42)),
static_cast<X43&&>(x43)), static_cast<X44&&>(x44)), static_cast<X45&&>(x45)), static_cast<X46&&>(x46)), static_cast<X47&&>(x47)), static_cast<X48&&>(x48)), static_cast<X49&&>(x49)),
static_cast<X50&&>(x50)), static_cast<X51&&>(x51)), static_cast<X52&&>(x52)), static_cast<X53&&>(x53)), static_cast<X54&&>(x54)), static_cast<X55&&>(x55)), static_cast<X56&&>(x56))
, static_cast<Xn&&>(xn)...);
}
};
//! @endcond
struct foldl1_t {
template <typename F, typename X1, typename ...Xn>
constexpr decltype(auto) operator()(F&& f, X1&& x1, Xn&& ...xn) const {
return foldl1_impl<sizeof...(xn) + 1>::apply(
static_cast<F&&>(f), static_cast<X1&&>(x1), static_cast<Xn&&>(xn)...
);
}
};
constexpr foldl1_t foldl1{};
constexpr auto foldl = foldl1;
}} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_VARIADIC_FOLDL1_HPP

View File

@@ -0,0 +1,210 @@
/*!
@file
Defines `boost::hana::detail::variadic::foldr1`.
@copyright Louis Dionne 2013-2017
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_DETAIL_VARIADIC_FOLDR1_HPP
#define BOOST_HANA_DETAIL_VARIADIC_FOLDR1_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
//! @cond
template <unsigned int n, typename = when<true>>
struct foldr1_impl;
template <>
struct foldr1_impl<1> {
template <typename F, typename X1>
static constexpr X1 apply(F&&, X1&& x1)
{ return static_cast<X1&&>(x1); }
};
template <>
struct foldr1_impl<2> {
template <typename F, typename X1, typename X2>
static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2) {
return static_cast<F&&>(f)(static_cast<X1&&>(x1),
static_cast<X2&&>(x2));
}
};
template <>
struct foldr1_impl<3> {
template <typename F, typename X1, typename X2, typename X3>
static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3) {
return f(static_cast<X1&&>(x1),
f(static_cast<X2&&>(x2),
static_cast<X3&&>(x3)));
}
};
template <>
struct foldr1_impl<4> {
template <typename F, typename X1, typename X2, typename X3, typename X4>
static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4) {
return f(static_cast<X1&&>(x1),
f(static_cast<X2&&>(x2),
f(static_cast<X3&&>(x3),
static_cast<X4&&>(x4))));
}
};
template <>
struct foldr1_impl<5> {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5>
static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5) {
return f(static_cast<X1&&>(x1),
f(static_cast<X2&&>(x2),
f(static_cast<X3&&>(x3),
f(static_cast<X4&&>(x4),
static_cast<X5&&>(x5)))));
}
};
template <>
struct foldr1_impl<6> {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6>
static constexpr decltype(auto) apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6) {
return f(static_cast<X1&&>(x1),
f(static_cast<X2&&>(x2),
f(static_cast<X3&&>(x3),
f(static_cast<X4&&>(x4),
f(static_cast<X5&&>(x5),
static_cast<X6&&>(x6))))));
}
};
template <unsigned int n>
struct foldr1_impl<n, when<(n >= 7) && (n < 14)>> {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename ...Xn>
static constexpr decltype(auto)
apply(F&& f
, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
, Xn&& ...xn)
{
return f(static_cast<X1&&>(x1),
f(static_cast<X2&&>(x2),
f(static_cast<X3&&>(x3),
f(static_cast<X4&&>(x4),
f(static_cast<X5&&>(x5),
f(static_cast<X6&&>(x6),
foldr1_impl<sizeof...(xn) + 1>::apply(f, static_cast<X7&&>(x7), static_cast<Xn&&>(xn)...)))))));
}
};
template <unsigned int n>
struct foldr1_impl<n, when<(n >= 14) && (n < 28)>> {
template <
typename F
, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7
, typename X8, typename X9, typename X10, typename X11, typename X12, typename X13, typename X14
, typename ...Xn
>
static constexpr decltype(auto)
apply(F&& f
, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
, X8&& x8, X9&& x9, X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14
, Xn&& ...xn)
{
return f(static_cast<X1&&>(x1), f(static_cast<X2&&>(x2), f(static_cast<X3&&>(x3), f(static_cast<X4&&>(x4), f(static_cast<X5&&>(x5), f(static_cast<X6&&>(x6), f(static_cast<X7&&>(x7),
f(static_cast<X8&&>(x8), f(static_cast<X9&&>(x9), f(static_cast<X10&&>(x10), f(static_cast<X11&&>(x11), f(static_cast<X12&&>(x12), f(static_cast<X13&&>(x13),
foldr1_impl<sizeof...(xn) + 1>::apply(f, static_cast<X14&&>(x14), static_cast<Xn&&>(xn)...))))))))))))));
}
};
template <unsigned int n>
struct foldr1_impl<n, when<(n >= 28) && (n < 56)>> {
template <
typename F
, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7
, typename X8, typename X9, typename X10, typename X11, typename X12, typename X13, typename X14
, typename X15, typename X16, typename X17, typename X18, typename X19, typename X20, typename X21
, typename X22, typename X23, typename X24, typename X25, typename X26, typename X27, typename X28
, typename ...Xn
>
static constexpr decltype(auto)
apply(F&& f
, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
, X8&& x8, X9&& x9, X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14
, X15&& x15, X16&& x16, X17&& x17, X18&& x18, X19&& x19, X20&& x20, X21&& x21
, X22&& x22, X23&& x23, X24&& x24, X25&& x25, X26&& x26, X27&& x27, X28&& x28
, Xn&& ...xn)
{
return f(static_cast<X1&&>(x1), f(static_cast<X2&&>(x2), f(static_cast<X3&&>(x3), f(static_cast<X4&&>(x4), f(static_cast<X5&&>(x5), f(static_cast<X6&&>(x6), f(static_cast<X7&&>(x7),
f(static_cast<X8&&>(x8), f(static_cast<X9&&>(x9), f(static_cast<X10&&>(x10), f(static_cast<X11&&>(x11), f(static_cast<X12&&>(x12), f(static_cast<X13&&>(x13), f(static_cast<X14&&>(x14),
f(static_cast<X15&&>(x15), f(static_cast<X16&&>(x16), f(static_cast<X17&&>(x17), f(static_cast<X18&&>(x18), f(static_cast<X19&&>(x19), f(static_cast<X20&&>(x20), f(static_cast<X21&&>(x21),
f(static_cast<X22&&>(x22), f(static_cast<X23&&>(x23), f(static_cast<X24&&>(x24), f(static_cast<X25&&>(x25), f(static_cast<X26&&>(x26), f(static_cast<X27&&>(x27),
foldr1_impl<sizeof...(xn) + 1>::apply(f, static_cast<X28&&>(x28), static_cast<Xn&&>(xn)...))))))))))))))))))))))))))));
}
};
template <unsigned int n>
struct foldr1_impl<n, when<(n >= 56)>> {
template <
typename F
, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7
, typename X8, typename X9, typename X10, typename X11, typename X12, typename X13, typename X14
, typename X15, typename X16, typename X17, typename X18, typename X19, typename X20, typename X21
, typename X22, typename X23, typename X24, typename X25, typename X26, typename X27, typename X28
, typename X29, typename X30, typename X31, typename X32, typename X33, typename X34, typename X35
, typename X36, typename X37, typename X38, typename X39, typename X40, typename X41, typename X42
, typename X43, typename X44, typename X45, typename X46, typename X47, typename X48, typename X49
, typename X50, typename X51, typename X52, typename X53, typename X54, typename X55, typename X56
, typename ...Xn
>
static constexpr decltype(auto)
apply(F&& f
, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7
, X8&& x8, X9&& x9, X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14
, X15&& x15, X16&& x16, X17&& x17, X18&& x18, X19&& x19, X20&& x20, X21&& x21
, X22&& x22, X23&& x23, X24&& x24, X25&& x25, X26&& x26, X27&& x27, X28&& x28
, X29&& x29, X30&& x30, X31&& x31, X32&& x32, X33&& x33, X34&& x34, X35&& x35
, X36&& x36, X37&& x37, X38&& x38, X39&& x39, X40&& x40, X41&& x41, X42&& x42
, X43&& x43, X44&& x44, X45&& x45, X46&& x46, X47&& x47, X48&& x48, X49&& x49
, X50&& x50, X51&& x51, X52&& x52, X53&& x53, X54&& x54, X55&& x55, X56&& x56
, Xn&& ...xn)
{
return f(static_cast<X1&&>(x1), f(static_cast<X2&&>(x2), f(static_cast<X3&&>(x3), f(static_cast<X4&&>(x4), f(static_cast<X5&&>(x5), f(static_cast<X6&&>(x6), f(static_cast<X7&&>(x7),
f(static_cast<X8&&>(x8), f(static_cast<X9&&>(x9), f(static_cast<X10&&>(x10), f(static_cast<X11&&>(x11), f(static_cast<X12&&>(x12), f(static_cast<X13&&>(x13), f(static_cast<X14&&>(x14),
f(static_cast<X15&&>(x15), f(static_cast<X16&&>(x16), f(static_cast<X17&&>(x17), f(static_cast<X18&&>(x18), f(static_cast<X19&&>(x19), f(static_cast<X20&&>(x20), f(static_cast<X21&&>(x21),
f(static_cast<X22&&>(x22), f(static_cast<X23&&>(x23), f(static_cast<X24&&>(x24), f(static_cast<X25&&>(x25), f(static_cast<X26&&>(x26), f(static_cast<X27&&>(x27), f(static_cast<X28&&>(x28),
f(static_cast<X29&&>(x29), f(static_cast<X30&&>(x30), f(static_cast<X31&&>(x31), f(static_cast<X32&&>(x32), f(static_cast<X33&&>(x33), f(static_cast<X34&&>(x34), f(static_cast<X35&&>(x35),
f(static_cast<X36&&>(x36), f(static_cast<X37&&>(x37), f(static_cast<X38&&>(x38), f(static_cast<X39&&>(x39), f(static_cast<X40&&>(x40), f(static_cast<X41&&>(x41), f(static_cast<X42&&>(x42),
f(static_cast<X43&&>(x43), f(static_cast<X44&&>(x44), f(static_cast<X45&&>(x45), f(static_cast<X46&&>(x46), f(static_cast<X47&&>(x47), f(static_cast<X48&&>(x48), f(static_cast<X49&&>(x49),
f(static_cast<X50&&>(x50), f(static_cast<X51&&>(x51), f(static_cast<X52&&>(x52), f(static_cast<X53&&>(x53), f(static_cast<X54&&>(x54), f(static_cast<X55&&>(x55),
foldr1_impl<sizeof...(xn) + 1>::apply(f, static_cast<X56&&>(x56), static_cast<Xn&&>(xn)...))))))))))))))))))))))))))))))))))))))))))))))))))))))));
}
};
//! @endcond
struct foldr1_t {
template <typename F, typename X1, typename ...Xn>
constexpr decltype(auto) operator()(F&& f, X1&& x1, Xn&& ...xn) const {
return foldr1_impl<sizeof...(xn) + 1>::apply(
static_cast<F&&>(f), static_cast<X1&&>(x1), static_cast<Xn&&>(xn)...
);
}
};
constexpr foldr1_t foldr1{};
struct foldr_t {
template <typename F, typename State, typename ...Xn>
constexpr decltype(auto) operator()(F&& f, State&& state, Xn&& ...xn) const {
return foldr1_impl<sizeof...(xn) + 1>::apply(
static_cast<F&&>(f), static_cast<Xn&&>(xn)..., static_cast<State&&>(state)
);
}
};
constexpr foldr_t foldr{};
}} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_VARIADIC_FOLDR1_HPP

View File

@@ -0,0 +1,27 @@
/*!
@file
Defines `boost::hana::detail::variadic::reverse_apply`.
@copyright Louis Dionne 2013-2017
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_DETAIL_VARIADIC_REVERSE_APPLY_HPP
#define BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/variadic/reverse_apply/unrolled.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
BOOST_HANA_CONSTEXPR_LAMBDA auto reverse_apply =
[](auto&& f, auto&& ...x) -> decltype(auto) {
return detail::variadic::reverse_apply_unrolled(
static_cast<decltype(f)>(f),
static_cast<decltype(x)>(x)...
);
};
}} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_HPP

View File

@@ -0,0 +1,41 @@
/*!
@file
Defines `boost::hana::detail::variadic::reverse_apply_flat`.
@copyright Louis Dionne 2013-2017
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_DETAIL_VARIADIC_REVERSE_APPLY_FLAT_HPP
#define BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_FLAT_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/variadic/at.hpp>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
template <int ...i, typename F, typename ...X>
constexpr decltype(auto)
reverse_apply_flat_helper(std::integer_sequence<int, i...>, F&& f, X&& ...x)
{
return static_cast<F&&>(f)(
detail::variadic::at<sizeof...(x) - i - 1>(
static_cast<X&&>(x)...
)...
);
}
template <typename F, typename ...X>
constexpr decltype(auto) reverse_apply_flat(F&& f, X&& ...x) {
return reverse_apply_flat_helper(
std::make_integer_sequence<int, sizeof...(x)>{},
static_cast<F&&>(f),
static_cast<X&&>(x)...
);
}
}} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_FLAT_HPP

View File

@@ -0,0 +1,87 @@
/*!
@file
Defines `boost::hana::detail::variadic::reverse_apply_unrolled`.
@copyright Louis Dionne 2013-2017
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_DETAIL_VARIADIC_REVERSE_APPLY_UNROLLED_HPP
#define BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_UNROLLED_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/functional/reverse_partial.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
struct reverse_apply_unrolled_impl {
template <typename F>
constexpr decltype(auto) operator()(F&& f) const {
return static_cast<F&&>(f)();
}
template <typename F, typename X1>
constexpr decltype(auto) operator()(F&& f, X1&& x1) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1)
);
}
template <typename F, typename X1, typename X2>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2) const {
return static_cast<F&&>(f)(
static_cast<X2&&>(x2),
static_cast<X1&&>(x1)
);
}
template <typename F, typename X1, typename X2, typename X3>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3) const {
return static_cast<F&&>(f)(
static_cast<X3&&>(x3),
static_cast<X2&&>(x2),
static_cast<X1&&>(x1)
);
}
template <typename F, typename X1, typename X2, typename X3, typename X4>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4) const {
return static_cast<F&&>(f)(
static_cast<X4&&>(x4),
static_cast<X3&&>(x3),
static_cast<X2&&>(x2),
static_cast<X1&&>(x1)
);
}
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5) const {
return static_cast<F&&>(f)(
static_cast<X5&&>(x5),
static_cast<X4&&>(x4),
static_cast<X3&&>(x3),
static_cast<X2&&>(x2),
static_cast<X1&&>(x1)
);
}
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename ...Xn>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, Xn&& ...xn) const {
return (*this)(hana::reverse_partial(
static_cast<F&&>(f)
, static_cast<X6&&>(x6)
, static_cast<X5&&>(x5)
, static_cast<X4&&>(x4)
, static_cast<X3&&>(x3)
, static_cast<X2&&>(x2)
, static_cast<X1&&>(x1)
), static_cast<Xn&&>(xn)...);
}
};
constexpr reverse_apply_unrolled_impl reverse_apply_unrolled{};
}} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_UNROLLED_HPP

View File

@@ -0,0 +1,153 @@
/*!
@file
Defines `boost::hana::detail::variadic::split_at`.
@copyright Louis Dionne 2013-2017
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_DETAIL_VARIADIC_SPLIT_AT_HPP
#define BOOST_HANA_DETAIL_VARIADIC_SPLIT_AT_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/functional/partial.hpp>
#include <boost/hana/functional/reverse_partial.hpp>
#include <cstddef>
BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
template <std::size_t n>
struct split_at_t {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8, Xs&& ...xs) const {
return split_at_t<n - 8>{}(
hana::partial(static_cast<F&&>(f),
static_cast<X1&&>(x1),
static_cast<X2&&>(x2),
static_cast<X3&&>(x3),
static_cast<X4&&>(x4),
static_cast<X5&&>(x5),
static_cast<X6&&>(x6),
static_cast<X7&&>(x7),
static_cast<X8&&>(x8)
),
static_cast<Xs&&>(xs)...
);
}
};
template <>
struct split_at_t<0> {
template <typename F, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, Xs&& ...xs) const {
return static_cast<F&&>(f)()(static_cast<Xs&&>(xs)...);
}
};
template <>
struct split_at_t<1> {
template <typename F, typename X1, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, Xs&& ...xs) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1)
)(static_cast<Xs&&>(xs)...);
}
};
template <>
struct split_at_t<2> {
template <typename F, typename X1, typename X2, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, Xs&& ...xs) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1),
static_cast<X2&&>(x2)
)(static_cast<Xs&&>(xs)...);
}
};
template <>
struct split_at_t<3> {
template <typename F, typename X1, typename X2, typename X3, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, Xs&& ...xs) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1),
static_cast<X2&&>(x2),
static_cast<X3&&>(x3)
)(static_cast<Xs&&>(xs)...);
}
};
template <>
struct split_at_t<4> {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, Xs&& ...xs) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1),
static_cast<X2&&>(x2),
static_cast<X3&&>(x3),
static_cast<X4&&>(x4)
)(static_cast<Xs&&>(xs)...);
}
};
template <>
struct split_at_t<5> {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, Xs&& ...xs) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1),
static_cast<X2&&>(x2),
static_cast<X3&&>(x3),
static_cast<X4&&>(x4),
static_cast<X5&&>(x5)
)(static_cast<Xs&&>(xs)...);
}
};
template <>
struct split_at_t<6> {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, Xs&& ...xs) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1),
static_cast<X2&&>(x2),
static_cast<X3&&>(x3),
static_cast<X4&&>(x4),
static_cast<X5&&>(x5),
static_cast<X6&&>(x6)
)(static_cast<Xs&&>(xs)...);
}
};
template <>
struct split_at_t<7> {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, Xs&& ...xs) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1),
static_cast<X2&&>(x2),
static_cast<X3&&>(x3),
static_cast<X4&&>(x4),
static_cast<X5&&>(x5),
static_cast<X6&&>(x6),
static_cast<X7&&>(x7)
)(static_cast<Xs&&>(xs)...);
}
};
template <std::size_t n>
struct _makesplit_at_t {
template <typename ...Xs>
constexpr decltype(auto) operator()(Xs&& ...xs) const {
return hana::reverse_partial(split_at_t<n>{},
static_cast<Xs&&>(xs)...);
}
};
template <std::size_t n>
constexpr _makesplit_at_t<n> split_at{};
}} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_VARIADIC_SPLIT_AT_HPP

View File

@@ -0,0 +1,51 @@
/*!
@file
Defines `boost::hana::detail::variadic::take`.
@copyright Louis Dionne 2013-2017
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_DETAIL_VARIADIC_TAKE_HPP
#define BOOST_HANA_DETAIL_VARIADIC_TAKE_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/variadic/split_at.hpp>
#include <boost/hana/functional/always.hpp>
#include <boost/hana/functional/reverse_partial.hpp>
#include <cstddef>
BOOST_HANA_NAMESPACE_BEGIN namespace detail { namespace variadic {
struct take_impl2 {
template <typename F, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, Xs&& ...xs) const {
return static_cast<F&&>(f)(static_cast<Xs&&>(xs)...);
}
};
struct take_impl1 {
template <typename ...Xs>
constexpr auto operator()(Xs&& ...xs) const {
return hana::always(
reverse_partial(take_impl2{},
static_cast<Xs&&>(xs)...)
);
}
};
template <std::size_t n>
struct take_t {
template <typename ...Xs>
constexpr decltype(auto) operator()(Xs&& ...xs) const {
return variadic::split_at<n>(static_cast<Xs&&>(xs)...)(take_impl1{});
}
};
template <std::size_t n>
constexpr take_t<n> take{};
}} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_VARIADIC_TAKE_HPP

View File

@@ -0,0 +1,21 @@
/*!
@file
Defines an equivalent to the proposed `std::void_t`.
@copyright Louis Dionne 2013-2017
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_DETAIL_VOID_T_HPP
#define BOOST_HANA_DETAIL_VOID_T_HPP
#include <boost/hana/config.hpp>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename ...>
using void_t = void;
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_VOID_T_HPP

View File

@@ -0,0 +1,33 @@
/*!
@file
Defines `boost::hana::detail::wrong`.
@copyright Louis Dionne 2013-2017
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_DETAIL_WRONG_HPP
#define BOOST_HANA_DETAIL_WRONG_HPP
#include <boost/hana/config.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
//! @ingroup group-detail
//! Equivalent to a type-dependent `std::false_type`.
//!
//! This is useful for making a static assertion that would otherwise
//! always fire up dependent on some template parameters.
//!
//!
//! Example
//! -------
//! @include example/detail/wrong.cpp
template <typename ...>
struct wrong : std::false_type { };
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_WRONG_HPP