stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork

This commit is contained in:
2026-02-24 18:38:47 +00:00
parent da8c28aaeb
commit 65cb2619a7
13106 changed files with 2484322 additions and 1804 deletions
@@ -0,0 +1,56 @@
/*!
@file
Defines `boost::hana::accessors`.
@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_ACCESSORS_HPP
#define BOOST_HANA_ACCESSORS_HPP
#include <boost/hana/fwd/accessors.hpp>
#include <boost/hana/concept/struct.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename S>
struct accessors_t {
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Struct<S>::value,
"hana::accessors<S> requires 'S' to be a Struct");
#endif
constexpr decltype(auto) operator()() const {
using Accessors = BOOST_HANA_DISPATCH_IF(accessors_impl<S>,
hana::Struct<S>::value
);
return Accessors::apply();
}
};
template <typename S, bool condition>
struct accessors_impl<S, when<condition>> : default_ {
template <typename ...Args>
static constexpr auto apply(Args&& ...) = delete;
};
namespace struct_detail {
template <typename ...>
struct is_valid { static constexpr bool value = true; };
}
template <typename S>
struct accessors_impl<S, when<
struct_detail::is_valid<typename S::hana_accessors_impl>::value
>>
: S::hana_accessors_impl
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_ACCESSORS_HPP
@@ -0,0 +1,17 @@
/*!
@file
Defines the `BOOST_HANA_ADAPT_ADT` macro.
@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_ADAPT_ADT_HPP
#define BOOST_HANA_ADAPT_ADT_HPP
#include <boost/hana/fwd/adapt_adt.hpp>
#include <boost/hana/detail/struct_macros.hpp>
#endif // !BOOST_HANA_ADAPT_ADT_HPP
@@ -0,0 +1,17 @@
/*!
@file
Defines the `BOOST_HANA_ADAPT_STRUCT` macro.
@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_ADAPT_STRUCT_HPP
#define BOOST_HANA_ADAPT_STRUCT_HPP
#include <boost/hana/fwd/adapt_struct.hpp>
#include <boost/hana/detail/struct_macros.hpp>
#endif // !BOOST_HANA_ADAPT_STRUCT_HPP
@@ -0,0 +1,55 @@
/*!
@file
Defines `boost::hana::adjust`.
@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_ADJUST_HPP
#define BOOST_HANA_ADJUST_HPP
#include <boost/hana/fwd/adjust.hpp>
#include <boost/hana/adjust_if.hpp>
#include <boost/hana/concept/functor.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/equal.hpp>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs, typename Value, typename F>
constexpr auto adjust_t::operator()(Xs&& xs, Value&& value, F&& f) const {
using S = typename hana::tag_of<Xs>::type;
using Adjust = BOOST_HANA_DISPATCH_IF(adjust_impl<S>,
hana::Functor<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Functor<S>::value,
"hana::adjust(xs, value, f) requires 'xs' to be a Functor");
#endif
return Adjust::apply(static_cast<Xs&&>(xs),
static_cast<Value&&>(value),
static_cast<F&&>(f));
}
//! @endcond
template <typename Fun, bool condition>
struct adjust_impl<Fun, when<condition>> : default_ {
template <typename Xs, typename Value, typename F>
static constexpr auto apply(Xs&& xs, Value&& value, F&& f) {
return hana::adjust_if(
static_cast<Xs&&>(xs),
hana::equal.to(static_cast<Value&&>(value)),
static_cast<F&&>(f)
);
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_ADJUST_HPP
@@ -0,0 +1,78 @@
/*!
@file
Defines `boost::hana::adjust_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_ADJUST_IF_HPP
#define BOOST_HANA_ADJUST_IF_HPP
#include <boost/hana/fwd/adjust_if.hpp>
#include <boost/hana/bool.hpp>
#include <boost/hana/concept/functor.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/if.hpp>
#include <boost/hana/transform.hpp>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs, typename Pred, typename F>
constexpr auto adjust_if_t::operator()(Xs&& xs, Pred const& pred, F const& f) const {
using S = typename hana::tag_of<Xs>::type;
using AdjustIf = BOOST_HANA_DISPATCH_IF(adjust_if_impl<S>,
hana::Functor<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Functor<S>::value,
"hana::adjust_if(xs, pred, f) requires 'xs' to be a Functor");
#endif
return AdjustIf::apply(static_cast<Xs&&>(xs), pred, f);
}
//! @endcond
namespace detail {
template <typename Pred, typename F>
struct apply_if {
Pred const& pred;
F const& f;
template <typename X>
constexpr decltype(auto) helper(bool cond, X&& x) const
{ return cond ? f(static_cast<X&&>(x)) : static_cast<X&&>(x); }
template <typename X>
constexpr decltype(auto) helper(hana::true_, X&& x) const
{ return f(static_cast<X&&>(x)); }
template <typename X>
constexpr decltype(auto) helper(hana::false_, X&& x) const
{ return static_cast<X&&>(x); }
template <typename X>
constexpr decltype(auto) operator()(X&& x) const {
auto cond = hana::if_(pred(x), hana::true_c, hana::false_c);
return this->helper(cond, static_cast<X&&>(x));
}
};
}
template <typename Fun, bool condition>
struct adjust_if_impl<Fun, when<condition>> : default_ {
template <typename Xs, typename Pred, typename F>
static constexpr auto apply(Xs&& xs, Pred const& pred, F const& f) {
return hana::transform(static_cast<Xs&&>(xs),
detail::apply_if<Pred, F>{pred, f});
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_ADJUST_IF_HPP
@@ -0,0 +1,48 @@
/*!
@file
Defines `boost::hana::all`.
@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_ALL_HPP
#define BOOST_HANA_ALL_HPP
#include <boost/hana/fwd/all.hpp>
#include <boost/hana/all_of.hpp>
#include <boost/hana/concept/searchable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/functional/id.hpp>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs>
constexpr auto all_t::operator()(Xs&& xs) const {
using S = typename hana::tag_of<Xs>::type;
using All = BOOST_HANA_DISPATCH_IF(all_impl<S>,
hana::Searchable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Searchable<S>::value,
"hana::all(xs) requires 'xs' to be a Searchable");
#endif
return All::apply(static_cast<Xs&&>(xs));
}
//! @endcond
template <typename S, bool condition>
struct all_impl<S, when<condition>> : default_ {
template <typename Xs>
static constexpr auto apply(Xs&& xs)
{ return hana::all_of(static_cast<Xs&&>(xs), hana::id); }
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_ALL_HPP
@@ -0,0 +1,51 @@
/*!
@file
Defines `boost::hana::all_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_ALL_OF_HPP
#define BOOST_HANA_ALL_OF_HPP
#include <boost/hana/fwd/all_of.hpp>
#include <boost/hana/any_of.hpp>
#include <boost/hana/concept/searchable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/functional/compose.hpp>
#include <boost/hana/not.hpp>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs, typename Pred>
constexpr auto all_of_t::operator()(Xs&& xs, Pred&& pred) const {
using S = typename hana::tag_of<Xs>::type;
using AllOf = BOOST_HANA_DISPATCH_IF(all_of_impl<S>,
hana::Searchable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Searchable<S>::value,
"hana::all_of(xs, pred) requires 'xs' to be a Searchable");
#endif
return AllOf::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
}
//! @endcond
template <typename S, bool condition>
struct all_of_impl<S, when<condition>> : default_ {
template <typename Xs, typename Pred>
static constexpr auto apply(Xs&& xs, Pred&& pred) {
return hana::not_(hana::any_of(static_cast<Xs&&>(xs),
hana::compose(hana::not_, static_cast<Pred&&>(pred))));
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_ALL_OF_HPP
@@ -0,0 +1,58 @@
/*!
@file
Defines `boost::hana::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_AND_HPP
#define BOOST_HANA_AND_HPP
#include <boost/hana/fwd/and.hpp>
#include <boost/hana/concept/logical.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/detail/variadic/foldl1.hpp>
#include <boost/hana/if.hpp>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename X, typename Y>
constexpr decltype(auto) and_t::operator()(X&& x, Y&& y) const {
using Bool = typename hana::tag_of<X>::type;
using And = BOOST_HANA_DISPATCH_IF(and_impl<Bool>,
hana::Logical<Bool>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Logical<Bool>::value,
"hana::and_(x, y) requires 'x' to be a Logical");
#endif
return And::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
}
template <typename X, typename ...Y>
constexpr decltype(auto) and_t::operator()(X&& x, Y&& ...y) const {
return detail::variadic::foldl1(
*this,
static_cast<X&&>(x),
static_cast<Y&&>(y)...
);
}
//! @endcond
template <typename L, bool condition>
struct and_impl<L, when<condition>> : default_ {
template <typename X, typename Y>
static constexpr decltype(auto) apply(X&& x, Y&& y) {
return hana::if_(x, static_cast<Y&&>(y), x);
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_AND_HPP
@@ -0,0 +1,48 @@
/*!
@file
Defines `boost::hana::any`.
@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_ANY_HPP
#define BOOST_HANA_ANY_HPP
#include <boost/hana/fwd/any.hpp>
#include <boost/hana/any_of.hpp>
#include <boost/hana/concept/searchable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/functional/id.hpp>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs>
constexpr auto any_t::operator()(Xs&& xs) const {
using S = typename hana::tag_of<Xs>::type;
using Any = BOOST_HANA_DISPATCH_IF(any_impl<S>,
hana::Searchable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Searchable<S>::value,
"hana::any(xs) requires 'xs' to be a Searchable");
#endif
return Any::apply(static_cast<Xs&&>(xs));
}
//! @endcond
template <typename S, bool condition>
struct any_impl<S, when<condition>> : default_ {
template <typename Xs>
static constexpr auto apply(Xs&& xs)
{ return hana::any_of(static_cast<Xs&&>(xs), hana::id); }
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_ANY_HPP
@@ -0,0 +1,192 @@
/*!
@file
Defines `boost::hana::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_ANY_OF_HPP
#define BOOST_HANA_ANY_OF_HPP
#include <boost/hana/fwd/any_of.hpp>
#include <boost/hana/accessors.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/bool.hpp>
#include <boost/hana/concept/searchable.hpp>
#include <boost/hana/concept/sequence.hpp>
#include <boost/hana/concept/struct.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/drop_front.hpp>
#include <boost/hana/first.hpp>
#include <boost/hana/front.hpp>
#include <boost/hana/functional/compose.hpp>
#include <boost/hana/if.hpp>
#include <boost/hana/is_empty.hpp>
#include <boost/hana/length.hpp>
#include <cstddef>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs, typename Pred>
constexpr auto any_of_t::operator()(Xs&& xs, Pred&& pred) const {
using S = typename hana::tag_of<Xs>::type;
using AnyOf = BOOST_HANA_DISPATCH_IF(any_of_impl<S>,
hana::Searchable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Searchable<S>::value,
"hana::any_of(xs, pred) requires 'xs' to be a Searchable");
#endif
return AnyOf::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
}
//! @endcond
template <typename S, bool condition>
struct any_of_impl<S, when<condition>> : default_ {
template <typename ...Args>
static constexpr auto apply(Args&& ...) = delete;
};
template <typename S>
struct any_of_impl<S, when<Sequence<S>::value>> {
//! @cond
template <std::size_t k, std::size_t Len>
struct any_of_helper {
template <typename Xs, typename Pred>
static constexpr auto apply(bool prev_cond, Xs&& xs, Pred&& pred) {
return prev_cond ? hana::true_c
: any_of_impl::any_of_helper<k + 1, Len>::apply(
hana::if_(pred(hana::at_c<k>(xs)), hana::true_c, hana::false_c),
static_cast<Xs&&>(xs),
static_cast<Pred&&>(pred)
);
}
template <typename Xs, typename Pred>
static constexpr auto apply(hana::true_, Xs&&, Pred&&)
{ return hana::true_c; }
template <typename Xs, typename Pred>
static constexpr auto apply(hana::false_, Xs&& xs, Pred&& pred) {
auto cond = hana::if_(pred(hana::at_c<k>(xs)), hana::true_c,
hana::false_c);
return any_of_impl::any_of_helper<k + 1, Len>::apply(cond,
static_cast<Xs&&>(xs),
static_cast<Pred&&>(pred));
}
};
template <std::size_t Len>
struct any_of_helper<Len, Len> {
template <typename Cond, typename Xs, typename Pred>
static constexpr auto apply(Cond cond, Xs&&, Pred&&)
{ return cond; }
};
template <typename Xs, typename Pred>
static constexpr auto apply(Xs&& xs, Pred&& pred) {
constexpr std::size_t len = decltype(hana::length(xs))::value;
return any_of_impl::any_of_helper<0, len>::apply(hana::false_c,
static_cast<Xs&&>(xs),
static_cast<Pred&&>(pred));
}
//! @endcond
};
template <typename It>
struct any_of_impl<It, when<
hana::Iterable<It>::value &&
!Sequence<It>::value
>> {
template <typename Xs, typename Pred>
static constexpr auto lazy_any_of_helper(hana::false_, bool prev_cond, Xs&& xs, Pred&& pred) {
decltype(auto) tail = hana::drop_front(static_cast<Xs&&>(xs));
constexpr bool done = decltype(hana::is_empty(tail))::value;
return prev_cond ? hana::true_c
: lazy_any_of_helper(hana::bool_<done>{},
hana::if_(pred(hana::front(xs)), hana::true_{}, hana::false_{}),
static_cast<decltype(tail)&&>(tail),
static_cast<Pred&&>(pred)
);
}
template <typename Xs, typename Pred>
static constexpr auto lazy_any_of_helper(hana::false_, hana::true_, Xs&&, Pred&&)
{ return hana::true_c; }
template <typename Xs, typename Pred>
static constexpr auto lazy_any_of_helper(hana::false_, hana::false_, Xs&& xs, Pred&& pred) {
constexpr bool done = decltype(hana::is_empty(hana::drop_front(xs)))::value;
return lazy_any_of_helper(hana::bool_c<done>,
hana::if_(pred(hana::front(xs)), hana::true_c, hana::false_c),
hana::drop_front(static_cast<Xs&&>(xs)),
static_cast<Pred&&>(pred)
);
}
template <typename Cond, typename Xs, typename Pred>
static constexpr auto lazy_any_of_helper(hana::true_, Cond cond, Xs&&, Pred&&)
{ return cond; }
template <typename Xs, typename Pred>
static constexpr auto apply(Xs&& xs, Pred&& pred) {
constexpr bool done = decltype(hana::is_empty(xs))::value;
return lazy_any_of_helper(hana::bool_c<done>, hana::false_c,
static_cast<Xs&&>(xs),
static_cast<Pred&&>(pred));
}
};
template <typename T, std::size_t N>
struct any_of_impl<T[N]> {
template <typename Xs, typename Pred>
static constexpr bool any_of_helper(bool cond, Xs&& xs, Pred&& pred) {
if (cond) return true;
for (std::size_t i = 1; i < N; ++i)
if (pred(static_cast<Xs&&>(xs)[i]))
return true;
return false;
}
// Since an array contains homogeneous data, if the predicate returns
// a compile-time logical at any index, it must do so at every index
// (because the type of the elements won't change)! In this case, we
// then only need to evaluate the predicate on the first element.
template <typename Xs, typename Pred>
static constexpr auto
any_of_helper(hana::true_, Xs&& /*xs*/, Pred&&)
{ return hana::true_c; }
template <typename Xs, typename Pred>
static constexpr auto
any_of_helper(hana::false_, Xs&&, Pred&&)
{ return hana::false_c; }
template <typename Xs, typename Pred>
static constexpr auto apply(Xs&& xs, Pred&& pred) {
auto cond = hana::if_(pred(static_cast<Xs&&>(xs)[0]), hana::true_c,
hana::false_c);
return any_of_helper(cond, static_cast<Xs&&>(xs),
static_cast<Pred&&>(pred));
}
};
template <typename S>
struct any_of_impl<S, when<hana::Struct<S>::value>> {
template <typename X, typename Pred>
static constexpr decltype(auto) apply(X const&, Pred&& pred) {
return hana::any_of(hana::accessors<S>(),
hana::compose(static_cast<Pred&&>(pred), hana::first));
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_ANY_OF_HPP
@@ -0,0 +1,78 @@
/*!
@file
Defines `boost::hana::ap`.
@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_AP_HPP
#define BOOST_HANA_AP_HPP
#include <boost/hana/fwd/ap.hpp>
#include <boost/hana/chain.hpp>
#include <boost/hana/concept/applicative.hpp>
#include <boost/hana/concept/sequence.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/detail/variadic/foldl1.hpp>
#include <boost/hana/functional/curry.hpp>
#include <boost/hana/functional/partial.hpp>
#include <boost/hana/transform.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename A, bool condition>
struct ap_impl<A, when<condition>> : default_ {
template <typename ...Args>
static constexpr auto apply(Args&& ...args) = delete;
};
//! @cond
template <typename F, typename X>
constexpr decltype(auto) ap_t::operator()(F&& f, X&& x) const {
using Function = typename hana::tag_of<F>::type;
using Value = typename hana::tag_of<X>::type;
using Ap = BOOST_HANA_DISPATCH_IF(ap_impl<Function>,
hana::Applicative<Function>::value && hana::Applicative<Value>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Applicative<Function>::value,
"hana::ap(f, x) requires 'f' to be an Applicative");
static_assert(hana::Applicative<Value>::value,
"hana::ap(f, x) requires 'x' to be an Applicative");
#endif
return Ap::apply(static_cast<F&&>(f), static_cast<X&&>(x));
}
template <typename F, typename ...Xs>
constexpr decltype(auto) ap_t::operator()(F&& f, Xs&& ...xs) const {
static_assert(sizeof...(xs) >= 1,
"hana::ap must be called with at least two arguments");
return detail::variadic::foldl1(
*this,
hana::transform(static_cast<F&&>(f), hana::curry<sizeof...(xs)>),
static_cast<Xs&&>(xs)...
);
}
//! @endcond
template <typename S>
struct ap_impl<S, when<Sequence<S>::value>> {
template <typename F, typename X>
static constexpr decltype(auto) apply(F&& f, X&& x) {
return hana::chain(
static_cast<F&&>(f),
hana::partial(hana::transform, static_cast<X&&>(x))
);
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_AP_HPP
@@ -0,0 +1,74 @@
/*!
@file
Defines `boost::hana::append`.
@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_APPEND_HPP
#define BOOST_HANA_APPEND_HPP
#include <boost/hana/fwd/append.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/concat.hpp>
#include <boost/hana/concept/monad_plus.hpp>
#include <boost/hana/concept/sequence.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/core/make.hpp>
#include <boost/hana/length.hpp>
#include <boost/hana/lift.hpp>
#include <cstddef>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs, typename X>
constexpr auto append_t::operator()(Xs&& xs, X&& x) const {
using M = typename hana::tag_of<Xs>::type;
using Append = BOOST_HANA_DISPATCH_IF(append_impl<M>,
hana::MonadPlus<M>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::MonadPlus<M>::value,
"hana::append(xs, x) requires 'xs' to be a MonadPlus");
#endif
return Append::apply(static_cast<Xs&&>(xs), static_cast<X&&>(x));
}
//! @endcond
template <typename M, bool condition>
struct append_impl<M, when<condition>> : default_ {
template <typename Xs, typename X>
static constexpr auto apply(Xs&& xs, X&& x) {
return hana::concat(static_cast<Xs&&>(xs),
hana::lift<M>(static_cast<X&&>(x)));
}
};
template <typename S>
struct append_impl<S, when<Sequence<S>::value>> {
template <typename Xs, typename X, std::size_t ...i>
static constexpr auto append_helper(Xs&& xs, X&& x, std::index_sequence<i...>) {
return hana::make<S>(
hana::at_c<i>(static_cast<Xs&&>(xs))..., static_cast<X&&>(x)
);
}
template <typename Xs, typename X>
static constexpr auto apply(Xs&& xs, X&& x) {
constexpr std::size_t N = decltype(hana::length(xs))::value;
return append_helper(static_cast<Xs&&>(xs), static_cast<X&&>(x),
std::make_index_sequence<N>{});
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_APPEND_HPP
@@ -0,0 +1,306 @@
/*!
@file
Defines macros to perform different kinds of assertions.
@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_ASSERT_HPP
#define BOOST_HANA_ASSERT_HPP
#include <boost/hana/concept/constant.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/preprocessor.hpp>
#include <boost/hana/if.hpp>
#include <boost/hana/value.hpp>
#include <cstdio>
#include <cstdlib>
#if defined(BOOST_HANA_DOXYGEN_INVOKED)
//! @ingroup group-assertions
//! Expands to a runtime assertion.
//!
//! Given a condition known at runtime, this macro expands to a runtime
//! assertion similar to the `assert` macro. The provided condition must
//! be explicitly convertible to a `bool`, and it must not be a model of
//! the `Constant` concept. If the condition is a `Constant`, a static
//! assertion will be triggered, asking you to use the
//! `BOOST_HANA_CONSTANT_ASSERT` macro instead.
//!
//! @note
//! This macro may only be used at function scope.
# define BOOST_HANA_RUNTIME_ASSERT(condition) unspecified
//! @ingroup group-assertions
//! Equivalent to `BOOST_HANA_RUNTIME_ASSERT`, but allows providing a
//! custom failure message.
//!
//! @warning
//! Conditions that contain multiple comma-separated elements should be
//! parenthesized.
# define BOOST_HANA_RUNTIME_ASSERT_MSG(condition, message) unspecified
//! @ingroup group-assertions
//! Compile-time assertion for `Constant`s.
//!
//! Given a condition known at compile-time in the form of a `Constant`,
//! this macro expands to a compile-time assertion similar to a `static_assert`.
//! The provided condition must be a model of the `Constant` concept, in
//! which case its value is retrieved using `hana::value` and then converted
//! to a `bool`. If the condition is not a `Constant`, a static assertion
//! will be triggered, asking you to use the `BOOST_HANA_RUNTIME_ASSERT`
//! macro instead.
//!
//! This macro may be used at global/namespace scope and function scope
//! only; it may not be used at class scope. Note that the condition may
//! never be evaluated at runtime. Hence, any side effect may not take
//! place (but you shouldn't rely on side effects inside assertions anyway).
# define BOOST_HANA_CONSTANT_ASSERT(condition) unspecified
//! @ingroup group-assertions
//! Equivalent to `BOOST_HANA_CONSTANT_ASSERT`, but allows providing a
//! custom failure message.
//!
//! @warning
//! Conditions that contain multiple comma-separated elements should be
//! parenthesized.
# define BOOST_HANA_CONSTANT_ASSERT_MSG(condition, message) unspecified
//! @ingroup group-assertions
//! Expands to the strongest form of assertion possible for the given
//! condition.
//!
//! Given a condition, `BOOST_HANA_ASSERT` expands either to a compile-time
//! or to a runtime assertion, depending on whether the value of the
//! condition is known at compile-time or at runtime. Compile-time
//! assertions are always preferred over runtime assertions. If the
//! condition is a model of the `Constant` concept, its value (retrievable
//! with `hana::value`) is assumed to be explicitly convertible to `bool`,
//! and a compile-time assertion is performed on it. Otherwise, the
//! condition itself is assumed to be explicitly convertible to `bool`,
//! and a runtime assertion is performed on it.
//!
//! If the assertion can be carried out at compile-time, the condition
//! is not guaranteed to be evaluated at runtime at all (but it may).
//! Hence, in general, you shouldn't rely on side effects that take place
//! inside an assertion.
//!
//! @note
//! This macro may only be used at function scope.
# define BOOST_HANA_ASSERT(condition) unspecified
//! @ingroup group-assertions
//! Equivalent to `BOOST_HANA_ASSERT`, but allows providing a custom
//! failure message.
//!
//! @warning
//! Conditions that contain multiple comma-separated elements should be
//! parenthesized.
# define BOOST_HANA_ASSERT_MSG(condition, message) unspecified
//! @ingroup group-assertions
//! Expands to a static assertion or a runtime assertion, depending on
//! whether `constexpr` lambdas are supported.
//!
//! This macro is used to assert on a condition that would be a constant
//! expression if constexpr lambdas were supported. Right now, constexpr
//! lambdas are not supported, and this is always a runtime assertion.
//! Specifically, this is equivalent to `BOOST_HANA_RUNTIME_ASSERT`.
# define BOOST_HANA_CONSTEXPR_ASSERT(condition) unspecified
//! @ingroup group-assertions
//! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT`, but allows providing a
//! custom failure message.
# define BOOST_HANA_CONSTEXPR_ASSERT_MSG(condition, message) unspecified
#elif defined(BOOST_HANA_CONFIG_DISABLE_ASSERTIONS)
# define BOOST_HANA_CONSTANT_ASSERT(...) /* nothing */
# define BOOST_HANA_CONSTANT_ASSERT_MSG(condition, message) /* nothing */
# define BOOST_HANA_RUNTIME_ASSERT(...) /* nothing */
# define BOOST_HANA_RUNTIME_ASSERT_MSG(condition, message) /* nothing */
# define BOOST_HANA_ASSERT(...) /* nothing */
# define BOOST_HANA_ASSERT_MSG(condition, message) /* nothing */
# define BOOST_HANA_CONSTEXPR_ASSERT(...) /* nothing */
# define BOOST_HANA_CONSTEXPR_ASSERT_MSG(condition, message) /* nothing */
#else
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_RUNTIME_ASSERT and BOOST_HANA_RUNTIME_ASSERT_MSG
//////////////////////////////////////////////////////////////////////////////
# define BOOST_HANA_RUNTIME_ASSERT_MSG(condition, message) \
BOOST_HANA_RUNTIME_CHECK_MSG(condition, message) \
/**/
# define BOOST_HANA_RUNTIME_ASSERT(...) \
BOOST_HANA_RUNTIME_CHECK(__VA_ARGS__) \
/**/
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_CONSTANT_ASSERT and BOOST_HANA_CONSTANT_ASSERT_MSG
//////////////////////////////////////////////////////////////////////////////
# define BOOST_HANA_CONSTANT_ASSERT_MSG(condition, message) \
BOOST_HANA_CONSTANT_CHECK_MSG(condition, message) \
/**/
# define BOOST_HANA_CONSTANT_ASSERT(...) \
BOOST_HANA_CONSTANT_CHECK(__VA_ARGS__) \
/**/
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_ASSERT and BOOST_HANA_ASSERT_MSG
//////////////////////////////////////////////////////////////////////////////
# define BOOST_HANA_ASSERT_MSG(condition, message) \
BOOST_HANA_CHECK_MSG(condition, message) \
/**/
# define BOOST_HANA_ASSERT(...) \
BOOST_HANA_CHECK(__VA_ARGS__) \
/**/
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_CONSTEXPR_ASSERT and BOOST_HANA_CONSTEXPR_ASSERT_MSG
//////////////////////////////////////////////////////////////////////////////
# define BOOST_HANA_CONSTEXPR_ASSERT_MSG(condition, message) \
BOOST_HANA_CONSTEXPR_CHECK_MSG(condition, message) \
/**/
# define BOOST_HANA_CONSTEXPR_ASSERT(...) \
BOOST_HANA_CONSTEXPR_CHECK(__VA_ARGS__) \
/**/
#endif
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_RUNTIME_CHECK and BOOST_HANA_RUNTIME_CHECK_MSG
//////////////////////////////////////////////////////////////////////////////
//! @ingroup group-assertions
//! Equivalent to `BOOST_HANA_RUNTIME_ASSERT_MSG`, but not influenced by the
//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
# define BOOST_HANA_RUNTIME_CHECK_MSG(condition, message) \
do { \
auto __hana_tmp = condition; \
static_assert(!::boost::hana::Constant<decltype(__hana_tmp)>::value,\
"the expression (" # condition ") yields a Constant; " \
"use BOOST_HANA_CONSTANT_ASSERT instead"); \
\
if (!static_cast<bool>(__hana_tmp)) { \
::std::fprintf(stderr, "Assertion failed: " \
"(%s), function %s, file %s, line %i.\n", \
message, __func__, __FILE__, __LINE__); \
::std::abort(); \
} \
} while (false); \
static_assert(true, "force trailing semicolon") \
/**/
//! @ingroup group-assertions
//! Equivalent to `BOOST_HANA_RUNTIME_ASSERT`, but not influenced by the
//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
# define BOOST_HANA_RUNTIME_CHECK(...) \
BOOST_HANA_RUNTIME_CHECK_MSG( \
(__VA_ARGS__), \
BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \
) \
/**/
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_CONSTANT_CHECK and BOOST_HANA_CONSTANT_CHECK_MSG
//////////////////////////////////////////////////////////////////////////////
//! @ingroup group-assertions
//! Equivalent to `BOOST_HANA_CONSTANT_ASSERT_MSG`, but not influenced by the
//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
# define BOOST_HANA_CONSTANT_CHECK_MSG(condition, message) \
auto BOOST_HANA_PP_CONCAT(__hana_tmp_, __LINE__) = condition; \
static_assert(::boost::hana::Constant< \
decltype(BOOST_HANA_PP_CONCAT(__hana_tmp_, __LINE__)) \
>::value, \
"the expression " # condition " does not yield a Constant; " \
"use BOOST_HANA_RUNTIME_ASSERT instead"); \
static_assert(::boost::hana::value< \
decltype(BOOST_HANA_PP_CONCAT(__hana_tmp_, __LINE__)) \
>(), message); \
static_assert(true, "force trailing semicolon") \
/**/
//! @ingroup group-assertions
//! Equivalent to `BOOST_HANA_CONSTANT_ASSERT`, but not influenced by the
//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
# define BOOST_HANA_CONSTANT_CHECK(...) \
BOOST_HANA_CONSTANT_CHECK_MSG( \
(__VA_ARGS__), \
BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \
) \
/**/
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_CHECK and BOOST_HANA_CHECK_MSG
//////////////////////////////////////////////////////////////////////////////
//! @ingroup group-assertions
//! Equivalent to `BOOST_HANA_ASSERT_MSG`, but not influenced by the
//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
# define BOOST_HANA_CHECK_MSG(condition, message) \
do { \
auto __hana_tmp = condition; \
::boost::hana::if_(::boost::hana::bool_c< \
::boost::hana::Constant<decltype(__hana_tmp)>::value>, \
[](auto expr) { \
static_assert(::boost::hana::value<decltype(expr)>(), \
message); \
}, \
[](auto expr) { \
if (!static_cast<bool>(expr)) { \
::std::fprintf(stderr, "Assertion failed: " \
"(%s), function %s, file %s, line %i.\n", \
message, __func__, __FILE__, __LINE__); \
::std::abort(); \
} \
} \
)(__hana_tmp); \
} while (false); \
static_assert(true, "force trailing semicolon") \
/**/
//! @ingroup group-assertions
//! Equivalent to `BOOST_HANA__ASSERT`, but not influenced by the
//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
# define BOOST_HANA_CHECK(...) \
BOOST_HANA_CHECK_MSG( \
(__VA_ARGS__), \
BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \
) \
/**/
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_CONSTEXPR_CHECK and BOOST_HANA_CONSTEXPR_CHECK_MSG
//////////////////////////////////////////////////////////////////////////////
//! @ingroup group-assertions
//! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT_MSG`, but not influenced by the
//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
# define BOOST_HANA_CONSTEXPR_CHECK_MSG(condition, message) \
BOOST_HANA_RUNTIME_CHECK_MSG(condition, message) \
/**/
//! @ingroup group-assertions
//! Equivalent to `BOOST_HANA_CONSTEXPR_ASSERT`, but not influenced by the
//! `BOOST_HANA_CONFIG_DISABLE_ASSERTIONS` config macro. For internal use only.
# define BOOST_HANA_CONSTEXPR_CHECK(...) \
BOOST_HANA_CONSTEXPR_CHECK_MSG( \
(__VA_ARGS__), \
BOOST_HANA_PP_STRINGIZE(__VA_ARGS__) \
) \
/**/
#endif // !BOOST_HANA_ASSERT_HPP
@@ -0,0 +1,57 @@
/*!
@file
Defines `boost::hana::at` and `boost::hana::at_c`.
@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_AT_HPP
#define BOOST_HANA_AT_HPP
#include <boost/hana/fwd/at.hpp>
#include <boost/hana/concept/integral_constant.hpp>
#include <boost/hana/concept/iterable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/integral_constant.hpp>
#include <cstddef>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs, typename N>
constexpr decltype(auto) at_t::operator()(Xs&& xs, N const& n) const {
using It = typename hana::tag_of<Xs>::type;
using At = BOOST_HANA_DISPATCH_IF(at_impl<It>,
hana::Iterable<It>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Iterable<It>::value,
"hana::at(xs, n) requires 'xs' to be an Iterable");
static_assert(hana::IntegralConstant<N>::value,
"hana::at(xs, n) requires 'n' to be an IntegralConstant");
#endif
return At::apply(static_cast<Xs&&>(xs), n);
}
//! @endcond
template <typename It, bool condition>
struct at_impl<It, when<condition>> : default_ {
template <typename ...Args>
static constexpr auto apply(Args&& ...) = delete;
};
template <std::size_t n, typename Xs>
constexpr decltype(auto) at_c(Xs&& xs) {
return hana::at(static_cast<Xs&&>(xs), hana::size_t<n>{});
}
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_AT_HPP
@@ -0,0 +1,121 @@
/*!
@file
Defines `boost::hana::at_key`.
@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_AT_KEY_HPP
#define BOOST_HANA_AT_KEY_HPP
#include <boost/hana/fwd/at_key.hpp>
#include <boost/hana/accessors.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/concept/searchable.hpp>
#include <boost/hana/concept/struct.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/detail/decay.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/find.hpp>
#include <boost/hana/find_if.hpp>
#include <boost/hana/first.hpp>
#include <boost/hana/functional/on.hpp>
#include <boost/hana/length.hpp>
#include <boost/hana/optional.hpp>
#include <boost/hana/second.hpp>
#include <cstddef>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs, typename Key>
constexpr decltype(auto) at_key_t::operator()(Xs&& xs, Key const& key) const {
using S = typename hana::tag_of<Xs>::type;
using AtKey = BOOST_HANA_DISPATCH_IF(at_key_impl<S>,
hana::Searchable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Searchable<S>::value,
"hana::at_key(xs, key) requires 'xs' to be Searchable");
#endif
return AtKey::apply(static_cast<Xs&&>(xs), key);
}
//! @endcond
template <typename S, bool condition>
struct at_key_impl<S, when<condition>> : default_ {
template <typename Xs, typename Key>
static constexpr auto apply(Xs&& xs, Key const& key) {
return hana::find(static_cast<Xs&&>(xs), key).value();
}
};
namespace at_key_detail {
template <typename T>
struct equal_to {
T const& t;
template <typename U>
constexpr auto operator()(U const& u) const {
return hana::equal(t, u);
}
};
//! @todo This causes an awful duplication of code with `find_if`.
template <typename Xs, typename Pred, std::size_t i, std::size_t N, bool Done>
struct advance_until;
template <typename Xs, typename Pred, std::size_t i, std::size_t N>
struct advance_until<Xs, Pred, i, N, false>
: advance_until<Xs, Pred, i + 1, N, static_cast<bool>(detail::decay<decltype(
std::declval<Pred>()(hana::at_c<i>(std::declval<Xs>()))
)>::type::value)>
{ };
template <typename Xs, typename Pred, std::size_t N>
struct advance_until<Xs, Pred, N, N, false> {
template <typename Ys>
static constexpr auto apply(Ys&&) = delete;
};
template <typename Xs, typename Pred, std::size_t i, std::size_t N>
struct advance_until<Xs, Pred, i, N, true> {
template <typename Ys>
static constexpr decltype(auto) apply(Ys&& ys) {
return hana::at_c<i - 1>(static_cast<Ys&&>(ys));
}
};
}
template <typename S>
struct at_key_impl<S, when<hana::Sequence<S>::value>> {
template <typename Xs, typename Key>
static constexpr decltype(auto) apply(Xs&& xs, Key const&) {
constexpr std::size_t N = decltype(hana::length(xs))::value;
using Pred = at_key_detail::equal_to<Key>;
return at_key_detail::advance_until<Xs&&, Pred, 0, N, false>::apply(
static_cast<Xs&&>(xs)
);
}
};
template <typename S>
struct at_key_impl<S, when<hana::Struct<S>::value>> {
template <typename X, typename Key>
static constexpr decltype(auto) apply(X&& x, Key const& key) {
auto accessor = hana::second(*hana::find_if(hana::accessors<S>(),
hana::equal.to(key) ^hana::on^ hana::first
));
return accessor(static_cast<X&&>(x));
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_AT_KEY_HPP
@@ -0,0 +1,53 @@
/*!
@file
Defines `boost::hana::back`.
@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_BACK_HPP
#define BOOST_HANA_BACK_HPP
#include <boost/hana/fwd/back.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/concept/iterable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/length.hpp>
#include <cstddef>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs>
constexpr decltype(auto) back_t::operator()(Xs&& xs) const {
using It = typename hana::tag_of<Xs>::type;
using Back = BOOST_HANA_DISPATCH_IF(back_impl<It>,
hana::Iterable<It>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Iterable<It>::value,
"hana::back(xs) requires 'xs' to be an Iterable");
#endif
return Back::apply(static_cast<Xs&&>(xs));
}
//! @endcond
template <typename It, bool condition>
struct back_impl<It, when<condition>> : default_ {
template <typename Xs>
static constexpr decltype(auto) apply(Xs&& xs) {
constexpr std::size_t len = decltype(hana::length(xs))::value;
static_assert(len > 0, "hana::back(xs) requires 'xs' to be non-empty");
return hana::at_c<len - 1>(static_cast<Xs&&>(xs));
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_BACK_HPP
@@ -0,0 +1,261 @@
/*!
@file
Defines `boost::hana::basic_tuple`.
@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_BASIC_TUPLE_HPP
#define BOOST_HANA_BASIC_TUPLE_HPP
#include <boost/hana/fwd/basic_tuple.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <boost/hana/detail/ebo.hpp>
#include <boost/hana/fwd/at.hpp>
#include <boost/hana/fwd/bool.hpp>
#include <boost/hana/fwd/concept/sequence.hpp>
#include <boost/hana/fwd/core/make.hpp>
#include <boost/hana/fwd/core/tag_of.hpp>
#include <boost/hana/fwd/drop_front.hpp>
#include <boost/hana/fwd/is_empty.hpp>
#include <boost/hana/fwd/transform.hpp>
#include <boost/hana/fwd/unpack.hpp>
#if 0 //! @todo Until we strip down headers, this includes too much
#include <boost/hana/fwd/integral_constant.hpp>
#include <boost/hana/fwd/length.hpp>
#endif
#include <cstddef>
#include <type_traits>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN
namespace detail {
//////////////////////////////////////////////////////////////////////
// basic_tuple_impl<n, Xn>
//////////////////////////////////////////////////////////////////////
template <std::size_t> struct bti; // basic_tuple_index
struct from_other { };
template <typename Indices, typename ...Xn>
struct basic_tuple_impl;
template <std::size_t ...n, typename ...Xn>
struct basic_tuple_impl<std::index_sequence<n...>, Xn...>
: detail::ebo<bti<n>, Xn>...
{
static constexpr std::size_t size_ = sizeof...(Xn);
constexpr basic_tuple_impl() = default;
template <typename Other>
explicit constexpr basic_tuple_impl(detail::from_other, Other&& other)
: detail::ebo<bti<n>, Xn>(detail::ebo_get<bti<n>>(static_cast<Other&&>(other)))...
{ }
template <typename ...Yn>
explicit constexpr basic_tuple_impl(Yn&& ...yn)
: detail::ebo<bti<n>, Xn>(static_cast<Yn&&>(yn))...
{ }
};
}
//////////////////////////////////////////////////////////////////////////
// basic_tuple
//////////////////////////////////////////////////////////////////////////
//! @cond
template <typename ...Xn>
struct basic_tuple final
: detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>
{
using Base = detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>;
constexpr basic_tuple() = default;
// copy constructor
template <typename Other, typename = typename std::enable_if<
std::is_same<typename detail::decay<Other>::type, basic_tuple>::value
>::type>
constexpr basic_tuple(Other&& other)
: Base(detail::from_other{}, static_cast<Other&&>(other))
{ }
template <typename ...Yn>
explicit constexpr basic_tuple(Yn&& ...yn)
: Base(static_cast<Yn&&>(yn)...)
{ }
};
//! @endcond
template <typename ...Xn>
struct tag_of<basic_tuple<Xn...>> {
using type = basic_tuple_tag;
};
//////////////////////////////////////////////////////////////////////////
// Foldable
//////////////////////////////////////////////////////////////////////////
template <>
struct unpack_impl<basic_tuple_tag> {
template <std::size_t ...i, typename ...Xn, typename F>
static constexpr decltype(auto)
apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F&& f) {
return static_cast<F&&>(f)(
detail::ebo_get<detail::bti<i>>(
static_cast<detail::ebo<detail::bti<i>, Xn> const&>(xs)
)...
);
}
template <std::size_t ...i, typename ...Xn, typename F>
static constexpr decltype(auto)
apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F&& f) {
return static_cast<F&&>(f)(
detail::ebo_get<detail::bti<i>>(
static_cast<detail::ebo<detail::bti<i>, Xn>&>(xs)
)...
);
}
template <std::size_t ...i, typename ...Xn, typename F>
static constexpr decltype(auto)
apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F&& f) {
return static_cast<F&&>(f)(
detail::ebo_get<detail::bti<i>>(
static_cast<detail::ebo<detail::bti<i>, Xn>&&>(xs)
)...
);
}
};
//////////////////////////////////////////////////////////////////////////
// Functor
//////////////////////////////////////////////////////////////////////////
template <>
struct transform_impl<basic_tuple_tag> {
template <std::size_t ...i, typename ...Xn, typename F>
static constexpr auto
apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F const& f) {
return hana::make_basic_tuple(
f(detail::ebo_get<detail::bti<i>>(
static_cast<detail::ebo<detail::bti<i>, Xn> const&>(xs)
))...
);
}
template <std::size_t ...i, typename ...Xn, typename F>
static constexpr auto
apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F const& f) {
return hana::make_basic_tuple(
f(detail::ebo_get<detail::bti<i>>(
static_cast<detail::ebo<detail::bti<i>, Xn>&>(xs)
))...
);
}
template <std::size_t ...i, typename ...Xn, typename F>
static constexpr auto
apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F const& f) {
return hana::make_basic_tuple(
f(detail::ebo_get<detail::bti<i>>(
static_cast<detail::ebo<detail::bti<i>, Xn>&&>(xs)
))...
);
}
};
//////////////////////////////////////////////////////////////////////////
// Iterable
//////////////////////////////////////////////////////////////////////////
template <>
struct at_impl<basic_tuple_tag> {
template <typename Xs, typename N>
static constexpr decltype(auto) apply(Xs&& xs, N const&) {
constexpr std::size_t index = N::value;
return detail::ebo_get<detail::bti<index>>(static_cast<Xs&&>(xs));
}
};
template <>
struct drop_front_impl<basic_tuple_tag> {
template <std::size_t N, typename Xs, std::size_t ...i>
static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
return hana::make_basic_tuple(
detail::ebo_get<detail::bti<i+N>>(static_cast<Xs&&>(xs))...
);
}
template <typename Xs, typename N>
static constexpr auto apply(Xs&& xs, N const&) {
constexpr std::size_t len = detail::decay<Xs>::type::size_;
return drop_front_helper<N::value>(static_cast<Xs&&>(xs), std::make_index_sequence<
N::value < len ? len - N::value : 0
>{});
}
};
template <>
struct is_empty_impl<basic_tuple_tag> {
template <typename ...Xs>
static constexpr hana::bool_<sizeof...(Xs) == 0>
apply(basic_tuple<Xs...> const&)
{ return {}; }
};
// compile-time optimizations (to reduce the # of function instantiations)
template <std::size_t n, typename ...Xs>
constexpr decltype(auto) at_c(basic_tuple<Xs...> const& xs) {
return detail::ebo_get<detail::bti<n>>(xs);
}
template <std::size_t n, typename ...Xs>
constexpr decltype(auto) at_c(basic_tuple<Xs...>& xs) {
return detail::ebo_get<detail::bti<n>>(xs);
}
template <std::size_t n, typename ...Xs>
constexpr decltype(auto) at_c(basic_tuple<Xs...>&& xs) {
return detail::ebo_get<detail::bti<n>>(static_cast<basic_tuple<Xs...>&&>(xs));
}
//////////////////////////////////////////////////////////////////////////
// Sequence
//////////////////////////////////////////////////////////////////////////
template <>
struct Sequence<basic_tuple_tag> {
static constexpr bool value = true;
};
template <>
struct make_impl<basic_tuple_tag> {
template <typename ...Xn>
static constexpr basic_tuple<typename detail::decay<Xn>::type...>
apply(Xn&& ...xn) {
return basic_tuple<typename detail::decay<Xn>::type...>{
static_cast<Xn&&>(xn)...
};
}
};
#if 0
//////////////////////////////////////////////////////////////////////////
// length
//////////////////////////////////////////////////////////////////////////
template <>
struct length_impl<basic_tuple_tag> {
template <typename ...Xn>
static constexpr auto apply(basic_tuple<Xn...> const&) {
return hana::size_c<sizeof...(Xn)>;
}
};
#endif
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_BASIC_TUPLE_HPP
@@ -0,0 +1,269 @@
/*!
@file
Defines the `Logical` and `Comparable` models of `boost::hana::integral_constant`.
@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_BOOL_HPP
#define BOOST_HANA_BOOL_HPP
#include <boost/hana/fwd/bool.hpp>
#include <boost/hana/concept/integral_constant.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/to.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/detail/operators/arithmetic.hpp>
#include <boost/hana/detail/operators/comparable.hpp>
#include <boost/hana/detail/operators/logical.hpp>
#include <boost/hana/detail/operators/orderable.hpp>
#include <boost/hana/eval.hpp>
#include <boost/hana/fwd/core/tag_of.hpp>
#include <boost/hana/fwd/eval_if.hpp>
#include <boost/hana/fwd/if.hpp>
#include <boost/hana/fwd/value.hpp>
#include <cstddef>
#include <type_traits>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN
//////////////////////////////////////////////////////////////////////////
// integral_constant
//////////////////////////////////////////////////////////////////////////
//! @cond
namespace ic_detail {
template <typename T, T N, typename = std::make_integer_sequence<T, N>>
struct go;
template <typename T, T N, T ...i>
struct go<T, N, std::integer_sequence<T, i...>> {
using swallow = T[];
template <typename F>
static constexpr void with_index(F&& f)
{ (void)swallow{T{}, ((void)f(integral_constant<T, i>{}), i)...}; }
template <typename F>
static constexpr void without_index(F&& f)
{ (void)swallow{T{}, ((void)f(), i)...}; }
};
template <typename T, T v>
template <typename F>
constexpr void with_index_t<T, v>::operator()(F&& f) const
{ go<T, ((void)sizeof(&f), v)>::with_index(static_cast<F&&>(f)); }
template <typename T, T v>
template <typename F>
constexpr void times_t<T, v>::operator()(F&& f) const
{ go<T, ((void)sizeof(&f), v)>::without_index(static_cast<F&&>(f)); }
// avoid link-time error
template <typename T, T v>
constexpr with_index_t<T, v> times_t<T, v>::with_index;
}
// avoid link-time error
template <typename T, T v>
constexpr ic_detail::times_t<T, v> integral_constant<T, v>::times;
template <typename T, T v>
struct tag_of<integral_constant<T, v>> {
using type = integral_constant_tag<T>;
};
//! @endcond
//////////////////////////////////////////////////////////////////////////
// Operators
//////////////////////////////////////////////////////////////////////////
namespace detail {
template <typename T>
struct comparable_operators<integral_constant_tag<T>> {
static constexpr bool value = true;
};
template <typename T>
struct orderable_operators<integral_constant_tag<T>> {
static constexpr bool value = true;
};
template <typename T>
struct arithmetic_operators<integral_constant_tag<T>> {
static constexpr bool value = true;
};
template <typename T>
struct logical_operators<integral_constant_tag<T>> {
static constexpr bool value = true;
};
}
#define BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(op) \
template <typename U, U u, typename V, V v> \
constexpr integral_constant<decltype(u op v), (u op v)> \
operator op(integral_constant<U, u>, integral_constant<V, v>) \
{ return {}; } \
/**/
#define BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(op) \
template <typename U, U u> \
constexpr integral_constant<decltype(op u), (op u)> \
operator op(integral_constant<U, u>) \
{ return {}; } \
/**/
// Arithmetic
BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(+)
// Bitwise
BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(~)
BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(&)
BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(|)
BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(^)
BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(<<)
BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(>>)
#undef BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP
#undef BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP
//////////////////////////////////////////////////////////////////////////
// User-defined literal
//////////////////////////////////////////////////////////////////////////
namespace ic_detail {
constexpr int to_int(char c) {
int result = 0;
if (c >= 'A' && c <= 'F') {
result = static_cast<int>(c) - static_cast<int>('A') + 10;
}
else if (c >= 'a' && c <= 'f') {
result = static_cast<int>(c) - static_cast<int>('a') + 10;
}
else {
result = static_cast<int>(c) - static_cast<int>('0');
}
return result;
}
template<std::size_t N>
constexpr long long parse(const char (&arr)[N]) {
long long base = 10;
std::size_t offset = 0;
if (N > 2) {
bool starts_with_zero = arr[0] == '0';
bool is_hex = starts_with_zero && arr[1] == 'x';
bool is_binary = starts_with_zero && arr[1] == 'b';
if (is_hex) {
//0xDEADBEEF (hexadecimal)
base = 16;
offset = 2;
}
else if (is_binary) {
//0b101011101 (binary)
base = 2;
offset = 2;
}
else if (starts_with_zero) {
//012345 (octal)
base = 8;
offset = 1;
}
}
long long number = 0;
long long multiplier = 1;
for (std::size_t i = 0; i < N - offset; ++i) {
char c = arr[N - 1 - i];
number += to_int(c) * multiplier;
multiplier *= base;
}
return number;
}
}
namespace literals {
template <char ...c>
constexpr auto operator"" _c() {
return hana::llong<ic_detail::parse<sizeof...(c)>({c...})>{};
}
}
//////////////////////////////////////////////////////////////////////////
// Model of Constant/IntegralConstant
//////////////////////////////////////////////////////////////////////////
template <typename T>
struct IntegralConstant<integral_constant_tag<T>> {
static constexpr bool value = true;
};
template <typename T, typename C>
struct to_impl<integral_constant_tag<T>, C, when<hana::IntegralConstant<C>::value>>
: embedding<is_embedded<typename C::value_type, T>::value>
{
template <typename N>
static constexpr auto apply(N const&)
{ return integral_constant<T, N::value>{}; }
};
//////////////////////////////////////////////////////////////////////////
// Optimizations
//////////////////////////////////////////////////////////////////////////
template <typename T>
struct eval_if_impl<integral_constant_tag<T>> {
template <typename Cond, typename Then, typename Else>
static constexpr decltype(auto)
apply(Cond const&, Then&& t, Else&& e) {
constexpr bool cond = static_cast<bool>(Cond::value);
return eval_if_impl::apply(hana::bool_<cond>{},
static_cast<Then&&>(t),
static_cast<Else&&>(e));
}
template <typename Then, typename Else>
static constexpr decltype(auto)
apply(hana::true_ const&, Then&& t, Else&&)
{ return hana::eval(static_cast<Then&&>(t)); }
template <typename Then, typename Else>
static constexpr decltype(auto)
apply(hana::false_ const&, Then&&, Else&& e)
{ return hana::eval(static_cast<Else&&>(e)); }
};
template <typename T>
struct if_impl<integral_constant_tag<T>> {
template <typename Cond, typename Then, typename Else>
static constexpr decltype(auto)
apply(Cond const&, Then&& t, Else&& e) {
constexpr bool cond = static_cast<bool>(Cond::value);
return if_impl::apply(hana::bool_<cond>{},
static_cast<Then&&>(t),
static_cast<Else&&>(e));
}
//! @todo We could return `Then` instead of `auto` to sometimes save
//! a copy, but that would break some code that would return a
//! reference to a `type` object. I think the code that would be
//! broken should be changed, but more thought needs to be given.
template <typename Then, typename Else>
static constexpr auto
apply(hana::true_ const&, Then&& t, Else&&)
{ return static_cast<Then&&>(t); }
template <typename Then, typename Else>
static constexpr auto
apply(hana::false_ const&, Then&&, Else&& e)
{ return static_cast<Else&&>(e); }
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_BOOL_HPP
@@ -0,0 +1,113 @@
/*!
@file
Defines `boost::hana::cartesian_product`.
@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_CARTESIAN_PRODUCT_HPP
#define BOOST_HANA_CARTESIAN_PRODUCT_HPP
#include <boost/hana/fwd/cartesian_product.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/concept/sequence.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/core/make.hpp>
#include <boost/hana/detail/array.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/length.hpp>
#include <boost/hana/unpack.hpp>
#include <cstddef>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs>
constexpr auto cartesian_product_t::operator()(Xs&& xs) const {
using S = typename hana::tag_of<Xs>::type;
using CartesianProduct = BOOST_HANA_DISPATCH_IF(
cartesian_product_impl<S>,
hana::Sequence<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Sequence<S>::value,
"hana::cartesian_product(xs) requires 'xs' to be a Sequence");
#endif
return CartesianProduct::apply(static_cast<Xs&&>(xs));
}
//! @endcond
namespace detail {
template <std::size_t ...Lengths>
struct cartesian_product_indices {
static constexpr std::size_t total_length() {
std::size_t lengths[] = {Lengths...};
std::size_t r = 1;
for (std::size_t len: lengths)
r *= len;
return r;
}
static constexpr std::size_t length = total_length();
static constexpr auto indices_of(std::size_t i) {
constexpr std::size_t lengths[] = {Lengths...};
constexpr std::size_t n = sizeof...(Lengths);
detail::array<std::size_t, n> result{};
for (std::size_t j = n; j--;) {
result[j] = i % lengths[j];
i /= lengths[j];
}
return result;
}
template <typename S, std::size_t n, std::size_t ...k, typename ...Xs>
static constexpr auto
product_element(std::index_sequence<k...>, Xs&& ...xs) {
constexpr auto indices = indices_of(n);
return hana::make<S>(hana::at_c<indices[k]>(xs)...);
}
template <typename S, std::size_t ...n, typename ...Xs>
static constexpr auto
create_product(std::index_sequence<n...>, Xs&& ...xs) {
return hana::make<S>(product_element<S, n>(
std::make_index_sequence<sizeof...(Xs)>{}, xs...
)...);
}
};
}
// Credits: implementation adapted from http://github.com/alexk7/hel.
template <typename S, bool condition>
struct cartesian_product_impl<S, when<condition>> : default_ {
template <typename Xs>
static constexpr auto apply(Xs&& xs) {
return hana::unpack(static_cast<Xs&&>(xs), cartesian_product_impl{});
}
template <typename ...Xs>
constexpr auto operator()(Xs&& ...xs) const {
using indices = detail::cartesian_product_indices<
decltype(hana::length(xs))::value...
>;
return indices::template create_product<S>(
std::make_index_sequence<indices::length>{},
static_cast<Xs&&>(xs)...);
}
constexpr auto operator()() const {
return hana::make<S>();
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CARTESIAN_PRODUCT_HPP
@@ -0,0 +1,50 @@
/*!
@file
Defines `boost::hana::chain`.
@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_CHAIN_HPP
#define BOOST_HANA_CHAIN_HPP
#include <boost/hana/fwd/chain.hpp>
#include <boost/hana/concept/monad.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/flatten.hpp>
#include <boost/hana/transform.hpp>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs, typename F>
constexpr decltype(auto) chain_t::operator()(Xs&& xs, F&& f) const {
using M = typename hana::tag_of<Xs>::type;
using Chain = BOOST_HANA_DISPATCH_IF(chain_impl<M>,
hana::Monad<M>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Monad<M>::value,
"hana::chain(xs, f) requires 'xs' to be a Monad");
#endif
return Chain::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f));
}
//! @endcond
template <typename M, bool condition>
struct chain_impl<M, when<condition>> : default_ {
template <typename Xs, typename F>
static constexpr auto apply(Xs&& xs, F&& f) {
return hana::flatten(hana::transform(static_cast<Xs&&>(xs),
static_cast<F&&>(f)));
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CHAIN_HPP
@@ -0,0 +1,44 @@
/*!
@file
Defines `boost::hana::comparing`.
@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_COMPARING_HPP
#define BOOST_HANA_COMPARING_HPP
#include <boost/hana/fwd/comparing.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <boost/hana/equal.hpp>
BOOST_HANA_NAMESPACE_BEGIN
namespace detail {
template <typename F>
struct equal_by {
F f;
template <typename X, typename Y>
constexpr auto operator()(X&& x, Y&& y) const&
{ return hana::equal(f(static_cast<X&&>(x)), f(static_cast<Y&&>(y))); }
template <typename X, typename Y>
constexpr auto operator()(X&& x, Y&& y) &
{ return hana::equal(f(static_cast<X&&>(x)), f(static_cast<Y&&>(y))); }
};
}
//! @cond
template <typename F>
constexpr auto comparing_t::operator()(F&& f) const {
return detail::equal_by<typename detail::decay<F>::type>{static_cast<F&&>(f)};
}
//! @endcond
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_COMPARING_HPP
@@ -0,0 +1,80 @@
/*!
@file
Defines `boost::hana::concat`.
@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_CONCAT_HPP
#define BOOST_HANA_CONCAT_HPP
#include <boost/hana/fwd/concat.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/concept/monad_plus.hpp>
#include <boost/hana/concept/sequence.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/core/make.hpp>
#include <boost/hana/length.hpp>
#include <cstddef>
#include <type_traits>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs, typename Ys>
constexpr auto concat_t::operator()(Xs&& xs, Ys&& ys) const {
using M = typename hana::tag_of<Xs>::type;
using Concat = BOOST_HANA_DISPATCH_IF(concat_impl<M>,
hana::MonadPlus<M>::value &&
std::is_same<typename hana::tag_of<Ys>::type, M>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(std::is_same<typename hana::tag_of<Ys>::type, M>::value,
"hana::concat(xs, ys) requires 'xs' and 'ys' to have the same tag");
static_assert(hana::MonadPlus<M>::value,
"hana::concat(xs, ys) requires 'xs' and 'ys' to be MonadPlus");
#endif
return Concat::apply(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys));
}
//! @endcond
template <typename M, bool condition>
struct concat_impl<M, when<condition>> : default_ {
template <typename ...Args>
static constexpr auto apply(Args&& ...) = delete;
};
template <typename S>
struct concat_impl<S, when<Sequence<S>::value>> {
template <typename Xs, typename Ys, std::size_t ...xi, std::size_t ...yi>
static constexpr auto
concat_helper(Xs&& xs, Ys&& ys, std::index_sequence<xi...>,
std::index_sequence<yi...>)
{
return hana::make<S>(
hana::at_c<xi>(static_cast<Xs&&>(xs))...,
hana::at_c<yi>(static_cast<Ys&&>(ys))...
);
}
template <typename Xs, typename Ys>
static constexpr auto apply(Xs&& xs, Ys&& ys) {
constexpr std::size_t xi = decltype(hana::length(xs))::value;
constexpr std::size_t yi = decltype(hana::length(ys))::value;
return concat_helper(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys),
std::make_index_sequence<xi>{},
std::make_index_sequence<yi>{});
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCAT_HPP
@@ -0,0 +1,36 @@
/*!
@file
Master header for the `boost/hana/concept/` subdirectory.
@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_CONCEPT_HPP
#define BOOST_HANA_CONCEPT_HPP
#include <boost/hana/concept/applicative.hpp>
#include <boost/hana/concept/comonad.hpp>
#include <boost/hana/concept/comparable.hpp>
#include <boost/hana/concept/constant.hpp>
#include <boost/hana/concept/euclidean_ring.hpp>
#include <boost/hana/concept/foldable.hpp>
#include <boost/hana/concept/functor.hpp>
#include <boost/hana/concept/group.hpp>
#include <boost/hana/concept/hashable.hpp>
#include <boost/hana/concept/integral_constant.hpp>
#include <boost/hana/concept/iterable.hpp>
#include <boost/hana/concept/logical.hpp>
#include <boost/hana/concept/metafunction.hpp>
#include <boost/hana/concept/monad.hpp>
#include <boost/hana/concept/monad_plus.hpp>
#include <boost/hana/concept/monoid.hpp>
#include <boost/hana/concept/orderable.hpp>
#include <boost/hana/concept/product.hpp>
#include <boost/hana/concept/ring.hpp>
#include <boost/hana/concept/searchable.hpp>
#include <boost/hana/concept/sequence.hpp>
#include <boost/hana/concept/struct.hpp>
#endif // !BOOST_HANA_CONCEPT_HPP
@@ -0,0 +1,33 @@
/*!
@file
Defines `boost::hana::Applicative`.
@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_CONCEPT_APPLICATIVE_HPP
#define BOOST_HANA_CONCEPT_APPLICATIVE_HPP
#include <boost/hana/fwd/concept/applicative.hpp>
#include <boost/hana/ap.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/lift.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename A>
struct Applicative
: hana::integral_constant<bool,
!is_default<ap_impl<typename tag_of<A>::type>>::value &&
!is_default<lift_impl<typename tag_of<A>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_APPLICATIVE_HPP
@@ -0,0 +1,35 @@
/*!
@file
Defines `boost::hana::Comonad`.
@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_CONCEPT_COMONAD_HPP
#define BOOST_HANA_CONCEPT_COMONAD_HPP
#include <boost/hana/fwd/concept/comonad.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/duplicate.hpp>
#include <boost/hana/extend.hpp>
#include <boost/hana/extract.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename W>
struct Comonad
: hana::integral_constant<bool,
!is_default<extract_impl<typename tag_of<W>::type>>::value &&
(!is_default<duplicate_impl<typename tag_of<W>::type>>::value ||
!is_default<extend_impl<typename tag_of<W>::type>>::value)
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_COMONAD_HPP
@@ -0,0 +1,32 @@
/*!
@file
Defines `boost::hana::Comparable`.
@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_CONCEPT_COMPARABLE_HPP
#define BOOST_HANA_CONCEPT_COMPARABLE_HPP
#include <boost/hana/fwd/concept/comparable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/equal.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename T>
struct Comparable
: hana::integral_constant<bool,
!is_default<equal_impl<typename tag_of<T>::type,
typename tag_of<T>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_COMPARABLE_HPP
@@ -0,0 +1,31 @@
/*!
@file
Defines `boost::hana::Constant`.
@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_CONCEPT_CONSTANT_HPP
#define BOOST_HANA_CONCEPT_CONSTANT_HPP
#include <boost/hana/fwd/concept/constant.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/value.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename C>
struct Constant
: hana::integral_constant<bool,
!is_default<value_impl<typename tag_of<C>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_CONSTANT_HPP
@@ -0,0 +1,35 @@
/*!
@file
Defines `boost::hana::EuclideanRing`.
@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_CONCEPT_EUCLIDEAN_RING_HPP
#define BOOST_HANA_CONCEPT_EUCLIDEAN_RING_HPP
#include <boost/hana/fwd/concept/euclidean_ring.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/div.hpp>
#include <boost/hana/mod.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename R>
struct EuclideanRing
: hana::integral_constant<bool,
!is_default<mod_impl<typename tag_of<R>::type,
typename tag_of<R>::type>>::value &&
!is_default<div_impl<typename tag_of<R>::type,
typename tag_of<R>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_EUCLIDEAN_RING_HPP
@@ -0,0 +1,33 @@
/*!
@file
Defines `boost::hana::Foldable`.
@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_CONCEPT_FOLDABLE_HPP
#define BOOST_HANA_CONCEPT_FOLDABLE_HPP
#include <boost/hana/fwd/concept/foldable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/fold_left.hpp>
#include <boost/hana/unpack.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename T>
struct Foldable
: hana::integral_constant<bool,
!is_default<fold_left_impl<typename tag_of<T>::type>>::value ||
!is_default<unpack_impl<typename tag_of<T>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_FOLDABLE_HPP
@@ -0,0 +1,33 @@
/*!
@file
Defines `boost::hana::Functor`.
@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_CONCEPT_FUNCTOR_HPP
#define BOOST_HANA_CONCEPT_FUNCTOR_HPP
#include <boost/hana/fwd/concept/functor.hpp>
#include <boost/hana/adjust_if.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/transform.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename F>
struct Functor
: hana::integral_constant<bool,
!is_default<transform_impl<typename tag_of<F>::type>>::value ||
!is_default<adjust_if_impl<typename tag_of<F>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_FUNCTOR_HPP
@@ -0,0 +1,34 @@
/*!
@file
Defines `boost::hana::Group`.
@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_CONCEPT_GROUP_HPP
#define BOOST_HANA_CONCEPT_GROUP_HPP
#include <boost/hana/fwd/concept/group.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/minus.hpp>
#include <boost/hana/negate.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename G>
struct Group
: hana::integral_constant<bool,
!is_default<negate_impl<typename tag_of<G>::type>>::value ||
!is_default<minus_impl<typename tag_of<G>::type,
typename tag_of<G>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_GROUP_HPP
@@ -0,0 +1,32 @@
/*!
@file
Defines `boost::hana::Hashable`.
@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_CONCEPT_HASHABLE_HPP
#define BOOST_HANA_CONCEPT_HASHABLE_HPP
#include <boost/hana/fwd/concept/hashable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/hash.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename T>
struct Hashable
: hana::integral_constant<bool,
!is_default<hash_impl<typename tag_of<T>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_HASHABLE_HPP
@@ -0,0 +1,43 @@
/*!
@file
Defines `boost::hana::IntegralConstant`.
@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_CONCEPT_INTEGRAL_CONSTANT_HPP
#define BOOST_HANA_CONCEPT_INTEGRAL_CONSTANT_HPP
#include <boost/hana/fwd/concept/integral_constant.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
BOOST_HANA_NAMESPACE_BEGIN
namespace detail {
template <typename C, typename Tag = typename tag_of<C>::type>
struct integral_constant_dispatch
: hana::integral_constant<bool,
hana::IntegralConstant<Tag>::value
>
{ };
template <typename C>
struct integral_constant_dispatch<C, C>
: hana::integral_constant<bool, false>
{ };
}
//! @cond
template <typename C>
struct IntegralConstant
: detail::integral_constant_dispatch<C>
{ };
//! @endcond
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_INTEGRAL_CONSTANT_HPP
@@ -0,0 +1,35 @@
/*!
@file
Defines `boost::hana::Iterable`.
@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_CONCEPT_ITERABLE_HPP
#define BOOST_HANA_CONCEPT_ITERABLE_HPP
#include <boost/hana/fwd/concept/iterable.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/drop_front.hpp>
#include <boost/hana/is_empty.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename It>
struct Iterable
: hana::integral_constant<bool,
!is_default<at_impl<typename tag_of<It>::type>>::value &&
!is_default<drop_front_impl<typename tag_of<It>::type>>::value &&
!is_default<is_empty_impl<typename tag_of<It>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_ITERABLE_HPP
@@ -0,0 +1,35 @@
/*!
@file
Defines `boost::hana::Logical`.
@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_CONCEPT_LOGICAL_HPP
#define BOOST_HANA_CONCEPT_LOGICAL_HPP
#include <boost/hana/fwd/concept/logical.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/eval_if.hpp>
#include <boost/hana/not.hpp>
#include <boost/hana/while.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename L>
struct Logical
: hana::integral_constant<bool,
!is_default<eval_if_impl<typename tag_of<L>::type>>::value &&
!is_default<not_impl<typename tag_of<L>::type>>::value &&
!is_default<while_impl<typename tag_of<L>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_LOGICAL_HPP
@@ -0,0 +1,41 @@
/*!
@file
Defines `boost::hana::Metafunction`.
@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_CONCEPT_METAFUNCTION_HPP
#define BOOST_HANA_CONCEPT_METAFUNCTION_HPP
#include <boost/hana/fwd/concept/metafunction.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
BOOST_HANA_NAMESPACE_BEGIN
namespace detail {
template <typename F, typename Tag = typename tag_of<F>::type>
struct metafunction_dispatch
: hana::integral_constant<bool,
Metafunction<Tag>::value
>
{ };
template <typename F>
struct metafunction_dispatch<F, F>
: hana::integral_constant<bool, false>
{ };
}
template <typename F>
struct Metafunction
: detail::metafunction_dispatch<F>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_METAFUNCTION_HPP
@@ -0,0 +1,33 @@
/*!
@file
Defines `boost::hana::Monad`.
@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_CONCEPT_MONAD_HPP
#define BOOST_HANA_CONCEPT_MONAD_HPP
#include <boost/hana/fwd/concept/monad.hpp>
#include <boost/hana/chain.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/flatten.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename M>
struct Monad
: hana::integral_constant<bool,
!is_default<flatten_impl<typename tag_of<M>::type>>::value ||
!is_default<chain_impl<typename tag_of<M>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_MONAD_HPP
@@ -0,0 +1,33 @@
/*!
@file
Defines `boost::hana::MonadPlus`.
@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_CONCEPT_MONAD_PLUS_HPP
#define BOOST_HANA_CONCEPT_MONAD_PLUS_HPP
#include <boost/hana/fwd/concept/monad_plus.hpp>
#include <boost/hana/concat.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/empty.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename M>
struct MonadPlus
: hana::integral_constant<bool,
!is_default<concat_impl<typename tag_of<M>::type>>::value &&
!is_default<empty_impl<typename tag_of<M>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_MONAD_PLUS_HPP
@@ -0,0 +1,34 @@
/*!
@file
Defines `boost::hana::Monoid`.
@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_CONCEPT_MONOID_HPP
#define BOOST_HANA_CONCEPT_MONOID_HPP
#include <boost/hana/fwd/concept/monoid.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/plus.hpp>
#include <boost/hana/zero.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename M>
struct Monoid
: hana::integral_constant<bool,
!is_default<zero_impl<typename tag_of<M>::type>>::value &&
!is_default<plus_impl<typename tag_of<M>::type,
typename tag_of<M>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_MONOID_HPP
@@ -0,0 +1,32 @@
/*!
@file
Defines `boost::hana::Orderable`.
@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_CONCEPT_ORDERABLE_HPP
#define BOOST_HANA_CONCEPT_ORDERABLE_HPP
#include <boost/hana/fwd/concept/orderable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/less.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename Ord>
struct Orderable
: hana::integral_constant<bool,
!is_default<less_impl<typename tag_of<Ord>::type,
typename tag_of<Ord>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_ORDERABLE_HPP
@@ -0,0 +1,33 @@
/*!
@file
Defines `boost::hana::Product`.
@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_CONCEPT_PRODUCT_HPP
#define BOOST_HANA_CONCEPT_PRODUCT_HPP
#include <boost/hana/fwd/concept/product.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/first.hpp>
#include <boost/hana/second.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename P>
struct Product
: hana::integral_constant<bool,
!is_default<first_impl<typename tag_of<P>::type>>::value &&
!is_default<second_impl<typename tag_of<P>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_PRODUCT_HPP
@@ -0,0 +1,34 @@
/*!
@file
Defines `boost::hana::Ring`.
@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_CONCEPT_RING_HPP
#define BOOST_HANA_CONCEPT_RING_HPP
#include <boost/hana/fwd/concept/ring.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/mult.hpp>
#include <boost/hana/one.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename R>
struct Ring
: hana::integral_constant<bool,
!is_default<one_impl<typename tag_of<R>::type>>::value &&
!is_default<mult_impl<typename tag_of<R>::type,
typename tag_of<R>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_RING_HPP
@@ -0,0 +1,33 @@
/*!
@file
Defines `boost::hana::Searchable`.
@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_CONCEPT_SEARCHABLE_HPP
#define BOOST_HANA_CONCEPT_SEARCHABLE_HPP
#include <boost/hana/fwd/concept/searchable.hpp>
#include <boost/hana/any_of.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/find_if.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename S>
struct Searchable
: hana::integral_constant<bool,
!is_default<any_of_impl<typename tag_of<S>::type>>::value &&
!is_default<find_if_impl<typename tag_of<S>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_SEARCHABLE_HPP
@@ -0,0 +1,44 @@
/*!
@file
Defines `boost::hana::Sequence`.
@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_CONCEPT_SEQUENCE_HPP
#define BOOST_HANA_CONCEPT_SEQUENCE_HPP
#include <boost/hana/fwd/concept/sequence.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/detail/integral_constant.hpp>
BOOST_HANA_NAMESPACE_BEGIN
namespace detail {
template <typename S, typename Tag = typename hana::tag_of<S>::type>
struct sequence_dispatch
: hana::integral_constant<bool,
hana::Sequence<Tag>::value
>
{ };
template <typename S>
struct sequence_dispatch<S, S>
: hana::integral_constant<bool, false>
{ };
}
//! @cond
template <typename S, bool condition>
struct Sequence<S, when<condition>>
: detail::sequence_dispatch<S>
{ };
//! @endcond
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_SEQUENCE_HPP
@@ -0,0 +1,31 @@
/*!
@file
Defines `boost::hana::Struct`.
@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_CONCEPT_STRUCT_HPP
#define BOOST_HANA_CONCEPT_STRUCT_HPP
#include <boost/hana/fwd/concept/struct.hpp>
#include <boost/hana/accessors.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
BOOST_HANA_NAMESPACE_BEGIN
template <typename S>
struct Struct
: hana::integral_constant<bool,
!is_default<accessors_impl<typename tag_of<S>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONCEPT_STRUCT_HPP
@@ -0,0 +1,219 @@
/*!
@file
Defines configuration macros used throughout the 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_CONFIG_HPP
#define BOOST_HANA_CONFIG_HPP
#include <boost/hana/version.hpp>
//////////////////////////////////////////////////////////////////////////////
// Detect the compiler
//////////////////////////////////////////////////////////////////////////////
#if defined(_MSC_VER) && !defined(__clang__) // MSVC
// This must be checked first, because otherwise it produces a fatal
// error due to unrecognized #warning directives used below.
# pragma message("Warning: the native Microsoft compiler is not supported due to lack of proper C++14 support.")
#elif defined(__clang__) && defined(_MSC_VER) // Clang-cl (Clang for Windows)
# define BOOST_HANA_CONFIG_CLANG BOOST_HANA_CONFIG_VERSION( \
__clang_major__, __clang_minor__, __clang_patchlevel__)
# if BOOST_HANA_CONFIG_CLANG < BOOST_HANA_CONFIG_VERSION(3, 5, 0)
# warning "Versions of Clang prior to 3.5.0 are not supported by Hana."
# endif
# if _MSC_VER < 1900
# warning "Clang-cl is only supported with the -fms-compatibility-version parameter set to 19 and above."
# endif
#elif defined(__clang__) && defined(__apple_build_version__) // Apple's Clang
# if __apple_build_version__ >= 6020049
# define BOOST_HANA_CONFIG_CLANG BOOST_HANA_CONFIG_VERSION(3, 6, 0)
# else
# warning "Versions of Apple's Clang prior to the one shipped with Xcode 6.3 are not supported by Hana."
# endif
#elif defined(__clang__) // genuine Clang
# define BOOST_HANA_CONFIG_CLANG BOOST_HANA_CONFIG_VERSION( \
__clang_major__, __clang_minor__, __clang_patchlevel__)
# if BOOST_HANA_CONFIG_CLANG < BOOST_HANA_CONFIG_VERSION(3, 5, 0)
# warning "Versions of Clang prior to 3.5.0 are not supported by Hana."
# endif
#elif defined(__GNUC__) // GCC
# define BOOST_HANA_CONFIG_GCC BOOST_HANA_CONFIG_VERSION( \
__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
# if BOOST_HANA_CONFIG_GCC < BOOST_HANA_CONFIG_VERSION(6, 0, 0)
# warning "Versions of GCC prior to 6.0.0 are not supported by Hana."
# endif
#else
# warning "Your compiler is not officially supported by Hana or it was not detected properly."
#endif
//////////////////////////////////////////////////////////////////////////////
// Check the compiler for general C++14 capabilities
//////////////////////////////////////////////////////////////////////////////
#if (__cplusplus < 201400)
# if defined(_MSC_VER)
# pragma message("Warning: Your compiler doesn't provide C++14 or higher capabilities. Try adding the compiler flag '-std=c++14' or '-std=c++1y'.")
# else
# warning "Your compiler doesn't provide C++14 or higher capabilities. Try adding the compiler flag '-std=c++14' or '-std=c++1y'."
# endif
#endif
//////////////////////////////////////////////////////////////////////////////
// Detect the standard library
//////////////////////////////////////////////////////////////////////////////
// We include this header, which normally defines the proper detection macros.
// At least, libc++ and libstdc++ do.
#include <cstddef>
#if defined(_LIBCPP_VERSION)
# define BOOST_HANA_CONFIG_LIBCPP BOOST_HANA_CONFIG_VERSION( \
((_LIBCPP_VERSION) / 1000) % 10, 0, (_LIBCPP_VERSION) % 1000)
# if BOOST_HANA_CONFIG_LIBCPP < BOOST_HANA_CONFIG_VERSION(1, 0, 101)
# warning "Versions of libc++ prior to the one shipped with Clang 3.5.0 are not supported by Hana."
# endif
#elif defined(__GLIBCXX__)
// We do not define a macro to keep track of libstdc++'s version, because
// we have no scalable way of associating a value of __GLIBCXX__ to the
// corresponding GCC release. Instead, we just check that the release date
// of the libstdc++ in use is recent enough, which should indicate that it
// was released with a GCC >= 5.1, which in turn indicates good enough C++14
// support.
# if __GLIBCXX__ < 20150422 // --> the libstdc++ shipped with GCC 5.1.0
# warning "Versions of libstdc++ prior to the one shipped with GCC 5.1.0 are not supported by Hana for lack of full C++14 support."
# endif
# define BOOST_HANA_CONFIG_LIBSTDCXX
#elif defined(_MSC_VER)
# define BOOST_HANA_CONFIG_LIBMSVCCXX
#else
# warning "Your standard library is not officially supported by Hana or it was not detected properly."
#endif
//////////////////////////////////////////////////////////////////////////////
// Caveats and other compiler-dependent options
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_CONFIG_HAS_CONSTEXPR_LAMBDA enables some constructs requiring
// `constexpr` lambdas, which are not in the language (yet).
// Currently always disabled.
//
// BOOST_HANA_CONSTEXPR_LAMBDA expands to `constexpr` if constexpr lambdas
// are supported and to nothing otherwise.
#if 0
# define BOOST_HANA_CONFIG_HAS_CONSTEXPR_LAMBDA
# define BOOST_HANA_CONSTEXPR_LAMBDA constexpr
#else
# define BOOST_HANA_CONSTEXPR_LAMBDA /* nothing */
#endif
// The std::tuple adapter is broken on libc++ prior to the one shipped
// with Clang 3.7.0.
#if defined(BOOST_HANA_CONFIG_LIBCPP) && \
BOOST_HANA_CONFIG_LIBCPP < BOOST_HANA_CONFIG_VERSION(1, 0, 101)
# define BOOST_HANA_CONFIG_HAS_NO_STD_TUPLE_ADAPTER
#endif
// There's a bug in std::tuple_cat in libc++ right now.
// See http://llvm.org/bugs/show_bug.cgi?id=22806.
#if defined(BOOST_HANA_CONFIG_LIBCPP)
# define BOOST_HANA_CONFIG_LIBCPP_HAS_BUG_22806
#endif
//////////////////////////////////////////////////////////////////////////////
// Namespace macros
//////////////////////////////////////////////////////////////////////////////
#define BOOST_HANA_NAMESPACE_BEGIN namespace boost { namespace hana {
#define BOOST_HANA_NAMESPACE_END }}
//////////////////////////////////////////////////////////////////////////////
// Library features and options that can be tweaked by users
//////////////////////////////////////////////////////////////////////////////
#if defined(BOOST_HANA_DOXYGEN_INVOKED) || \
(defined(NDEBUG) && !defined(BOOST_HANA_CONFIG_DISABLE_ASSERTIONS))
//! @ingroup group-config
//! Disables the `BOOST_HANA_*_ASSERT` macro & friends.
//!
//! When this macro is defined, the `BOOST_HANA_*_ASSERT` macro & friends
//! are disabled, i.e. they expand to nothing.
//!
//! This macro is defined automatically when `NDEBUG` is defined. It can
//! also be defined by users before including this header or defined on
//! the command line.
# define BOOST_HANA_CONFIG_DISABLE_ASSERTIONS
#endif
#if defined(BOOST_HANA_DOXYGEN_INVOKED)
//! @ingroup group-config
//! Disables concept checks in interface methods.
//!
//! When this macro is not defined (the default), tag-dispatched methods
//! will make sure the arguments they are passed are models of the proper
//! concept(s). This can be very helpful in catching programming errors,
//! but it is also slightly less compile-time efficient. You should
//! probably always leave the checks enabled (and hence never define this
//! macro), except perhaps in translation units that are compiled very
//! often but whose code using Hana is modified very rarely.
# define BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
#endif
#if defined(BOOST_HANA_DOXYGEN_INVOKED)
//! @ingroup group-config
//! Enables usage of the "string literal operator template" GNU extension.
//!
//! That operator is not part of the language yet, but it is supported by
//! both Clang and GCC. This operator allows Hana to provide the nice `_s`
//! user-defined literal for creating compile-time strings.
//!
//! When this macro is not defined, the GNU extension will be not used
//! by Hana. Because this is a non-standard extension, the macro is not
//! defined by default.
# define BOOST_HANA_CONFIG_ENABLE_STRING_UDL
#endif
#if defined(BOOST_HANA_DOXYGEN_INVOKED)
//! @ingroup group-config
//! Enables additional assertions and sanity checks to be done by Hana.
//!
//! When this macro is defined (it is __not defined__ by default),
//! additional sanity checks may be done by Hana. These checks may
//! be costly to perform, either in terms of compilation time or in
//! terms of execution time. These checks may help debugging an
//! application during its initial development, but they should not
//! be enabled as part of the normal configuration.
# define BOOST_HANA_CONFIG_ENABLE_DEBUG_MODE
#endif
#endif // !BOOST_HANA_CONFIG_HPP
@@ -0,0 +1,51 @@
/*!
@file
Defines `boost::hana::contains` and `boost::hana::in`.
@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_CONTAINS_HPP
#define BOOST_HANA_CONTAINS_HPP
#include <boost/hana/fwd/contains.hpp>
#include <boost/hana/any_of.hpp>
#include <boost/hana/concept/searchable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/equal.hpp>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs, typename Key>
constexpr auto contains_t::operator()(Xs&& xs, Key&& key) const {
using S = typename hana::tag_of<Xs>::type;
using Contains = BOOST_HANA_DISPATCH_IF(contains_impl<S>,
hana::Searchable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Searchable<S>::value,
"hana::contains(xs, key) requires 'xs' to be a Searchable");
#endif
return Contains::apply(static_cast<Xs&&>(xs),
static_cast<Key&&>(key));
}
//! @endcond
template <typename S, bool condition>
struct contains_impl<S, when<condition>> : default_ {
template <typename Xs, typename X>
static constexpr auto apply(Xs&& xs, X&& x) {
return hana::any_of(static_cast<Xs&&>(xs),
hana::equal.to(static_cast<X&&>(x)));
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CONTAINS_HPP
@@ -0,0 +1,22 @@
/*!
@file
Defines the @ref group-core module.
@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_CORE_HPP
#define BOOST_HANA_CORE_HPP
#include <boost/hana/core/common.hpp>
#include <boost/hana/core/to.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/core/is_a.hpp>
#include <boost/hana/core/make.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/core/when.hpp>
#endif // !BOOST_HANA_CORE_HPP
@@ -0,0 +1,109 @@
/*!
@file
Defines `boost::hana::common` and `boost::hana::common_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_CORE_COMMON_HPP
#define BOOST_HANA_CORE_COMMON_HPP
#include <boost/hana/fwd/core/common.hpp>
#include <boost/hana/concept/constant.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/detail/canonical_constant.hpp>
#include <boost/hana/detail/std_common_type.hpp>
#include <boost/hana/detail/void_t.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN
//////////////////////////////////////////////////////////////////////////
// common
//////////////////////////////////////////////////////////////////////////
//! @cond
template <typename T, typename U, typename>
struct common : common<T, U, when<true>> { };
//! @endcond
template <typename T, typename U, bool condition>
struct common<T, U, when<condition>>
: detail::std_common_type<T, U>
{ };
template <typename T>
struct common<T, T> {
using type = T;
};
//////////////////////////////////////////////////////////////////////////
// has_common
//////////////////////////////////////////////////////////////////////////
template <typename T, typename U, typename>
struct has_common : std::false_type { };
template <typename T, typename U>
struct has_common<T, U, detail::void_t<typename common<T, U>::type>>
: std::true_type
{ };
//////////////////////////////////////////////////////////////////////////
// Provided common data types for Constants
//////////////////////////////////////////////////////////////////////////
namespace constant_detail {
//! @todo
//! This is an awful hack to avoid having
//! @code
//! common<integral_constant_tag<int>, integral_constant_tag<long>>
//! ==
//! CanonicalConstant<long>
//! @endcode
template <typename A, typename B, typename C>
struct which {
using type = detail::CanonicalConstant<C>;
};
template <template <typename ...> class A, typename T, typename U, typename C>
struct which<A<T>, A<U>, C> {
using type = A<C>;
};
}
template <typename A, typename B>
struct common<A, B, when<
hana::Constant<A>::value &&
hana::Constant<B>::value &&
has_common<typename A::value_type, typename B::value_type>::value
>> {
using type = typename constant_detail::which<
A, B,
typename common<typename A::value_type,
typename B::value_type>::type
>::type;
};
template <typename A, typename B>
struct common<A, B, when<
hana::Constant<A>::value &&
!hana::Constant<B>::value &&
has_common<typename A::value_type, B>::value
>> {
using type = typename common<typename A::value_type, B>::type;
};
template <typename A, typename B>
struct common<A, B, when<
!hana::Constant<A>::value &&
hana::Constant<B>::value &&
has_common<A, typename B::value_type>::value
>> {
using type = typename common<A, typename B::value_type>::type;
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CORE_COMMON_HPP
@@ -0,0 +1,32 @@
/*!
@file
Defines `boost::hana::default_` and `boost::hana::is_default`.
@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_CORE_DEFAULT_HPP
#define BOOST_HANA_CORE_DEFAULT_HPP
#include <boost/hana/fwd/core/default.hpp>
#include <boost/hana/config.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN
template <typename Method, typename>
struct is_default : std::false_type { };
template <typename Method>
struct is_default<Method, decltype((void)
static_cast<default_>(*(Method*)0)
)>
: std::true_type
{ };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CORE_DEFAULT_HPP
@@ -0,0 +1,18 @@
/*!
@file
Includes all the headers needed to setup tag-dispatching.
@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_CORE_DISPATCH_HPP
#define BOOST_HANA_CORE_DISPATCH_HPP
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/dispatch_if.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/when.hpp>
#endif // !BOOST_HANA_CORE_DISPATCH_HPP
@@ -0,0 +1,41 @@
/*!
@file
Defines `boost::hana::is_a` and `boost::hana::is_an`.
@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_CORE_IS_A_HPP
#define BOOST_HANA_CORE_IS_A_HPP
#include <boost/hana/fwd/core/is_a.hpp>
#include <boost/hana/bool.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <type_traits>
BOOST_HANA_NAMESPACE_BEGIN
//////////////////////////////////////////////////////////////////////////
// is_a
//////////////////////////////////////////////////////////////////////////
template <typename DataType, typename T>
struct is_a_t<DataType, T>
: integral_constant<bool,
std::is_same<DataType, typename hana::tag_of<T>::type>::value
>
{ };
template <typename DataType>
struct is_a_t<DataType> {
template <typename T>
constexpr auto operator()(T const&) const
{ return hana::is_a<DataType, T>; }
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CORE_IS_A_HPP
@@ -0,0 +1,45 @@
/*!
@file
Defines `boost::hana::make`.
@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_CORE_MAKE_HPP
#define BOOST_HANA_CORE_MAKE_HPP
#include <boost/hana/fwd/core/make.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/when.hpp>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Datatype, typename>
struct make_impl : make_impl<Datatype, when<true>> { };
//! @endcond
template <typename Datatype, bool condition>
struct make_impl<Datatype, when<condition>> : default_ {
template <typename ...X>
static constexpr auto make_helper(int, X&& ...x)
-> decltype(Datatype(static_cast<X&&>(x)...))
{ return Datatype(static_cast<X&&>(x)...); }
template <typename ...X>
static constexpr auto make_helper(long, X&& ...) {
static_assert((sizeof...(X), false),
"there exists no constructor for the given data type");
}
template <typename ...X>
static constexpr decltype(auto) apply(X&& ...x)
{ return make_helper(int{}, static_cast<X&&>(x)...); }
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CORE_MAKE_HPP
@@ -0,0 +1,49 @@
/*!
@file
Defines `boost::hana::tag_of` and `boost::hana::tag_of_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_CORE_TAG_OF_HPP
#define BOOST_HANA_CORE_TAG_OF_HPP
#include <boost/hana/fwd/core/tag_of.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename T, typename>
struct tag_of : tag_of<T, when<true>> { };
//! @endcond
namespace core_detail {
template <typename ...>
struct is_valid { static constexpr bool value = true; };
}
template <typename T, bool condition>
struct tag_of<T, when<condition>> {
using type = T;
};
template <typename T>
struct tag_of<T, when<
core_detail::is_valid<typename T::hana_tag>::value
>> {
using type = typename T::hana_tag;
};
template <typename T> struct tag_of<T const> : tag_of<T> { };
template <typename T> struct tag_of<T volatile> : tag_of<T> { };
template <typename T> struct tag_of<T const volatile> : tag_of<T> { };
template <typename T> struct tag_of<T&> : tag_of<T> { };
template <typename T> struct tag_of<T&&> : tag_of<T> { };
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CORE_TAG_OF_HPP
@@ -0,0 +1,194 @@
/*!
@file
Defines `boost::hana::to` and related utilities.
@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_CORE_TO_HPP
#define BOOST_HANA_CORE_TO_HPP
#include <boost/hana/fwd/core/to.hpp>
#include <boost/hana/concept/constant.hpp>
#include <boost/hana/concept/foldable.hpp>
#include <boost/hana/concept/sequence.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/common.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/core/make.hpp>
#include <boost/hana/detail/wrong.hpp>
#include <boost/hana/unpack.hpp>
#include <boost/hana/value.hpp>
#include <type_traits>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN
//////////////////////////////////////////////////////////////////////////
// to
//////////////////////////////////////////////////////////////////////////
//! @cond
template <typename To, typename From, typename>
struct to_impl : to_impl<To, From, when<true>> { };
//! @endcond
namespace convert_detail {
struct no_conversion { };
template <typename ...>
struct is_valid { static constexpr bool value = true; };
}
template <typename To, typename From, bool condition>
struct to_impl<To, From, when<condition>> : convert_detail::no_conversion {
template <typename X>
static constexpr auto apply(X const&) {
static_assert(detail::wrong<to_impl<To, From>, X>{},
"no conversion is available between the provided types");
}
};
template <typename To, typename From>
struct to_impl<To, From, when<convert_detail::is_valid<
decltype(static_cast<To>(std::declval<From>()))
>::value>> {
template <typename X>
static constexpr To apply(X&& x)
{ return static_cast<To>(static_cast<X&&>(x)); }
};
template <typename To>
struct to_impl<To, To> : embedding<> {
template <typename X>
static constexpr X apply(X&& x)
{ return static_cast<X&&>(x); }
};
//! @cond
template <typename To>
template <typename X>
constexpr decltype(auto) to_t<To>::operator()(X&& x) const {
using From = typename hana::tag_of<X>::type;
return to_impl<To, From>::apply(static_cast<X&&>(x));
}
//! @endcond
#define BOOST_HANA_DEFINE_EMBEDDING_IMPL(TO, FROM) \
template <> \
struct to_impl<TO, FROM> : embedding<> \
{ static constexpr TO apply(FROM x) { return x; } } \
/**/
BOOST_HANA_DEFINE_EMBEDDING_IMPL(long double, double);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(long double, float);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(double , float);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed long);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed int);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed short);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long long, signed char);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed int);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed short);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed long , signed char);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed int , signed short);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed int , signed char);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(signed short , signed char);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned long);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned int);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned short);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned char);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned int);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned short);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned long , unsigned char);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned int , unsigned short);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned int , unsigned char);
BOOST_HANA_DEFINE_EMBEDDING_IMPL(unsigned short , unsigned char);
#undef BOOST_HANA_DEFINE_EMBEDDING_IMPL
namespace detail {
template <typename T>
struct copy_char_signedness {
using type = typename std::conditional<std::is_signed<char>::value,
std::make_signed<T>, std::make_unsigned<T>
>::type::type;
};
}
// If `char` is signed, we define an embedding from `char` to any signed
// integral type. Otherwise, we define one from `char` to any unsigned
// integral type.
#define BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(TO) \
template <> \
struct to_impl<detail::copy_char_signedness<TO>::type, char> \
: embedding<> \
{ \
static constexpr detail::copy_char_signedness<TO>::type \
apply(char x) \
{ return x; } \
} \
/**/
BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(long long);
BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(long);
BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(int);
BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL(short);
#undef BOOST_HANA_DEFINE_CHAR_EMBEDDING_IMPL
template <typename T>
struct to_impl<T*, decltype(nullptr)> : embedding<> {
static constexpr T* apply(decltype(nullptr)) { return nullptr; }
};
//////////////////////////////////////////////////////////////////////////
// is_convertible
//////////////////////////////////////////////////////////////////////////
template <typename From, typename To, typename>
struct is_convertible : std::true_type { };
template <typename From, typename To>
struct is_convertible<From, To, decltype((void)
static_cast<convert_detail::no_conversion>(*(to_impl<To, From>*)0)
)> : std::false_type { };
//////////////////////////////////////////////////////////////////////////
// is_embedded
//////////////////////////////////////////////////////////////////////////
template <typename From, typename To, typename>
struct is_embedded : std::false_type { };
template <typename From, typename To>
struct is_embedded<From, To, decltype((void)
static_cast<embedding<true>>(*(to_impl<To, From>*)0)
)> : std::true_type { };
//////////////////////////////////////////////////////////////////////////
// Conversion for Constants
//////////////////////////////////////////////////////////////////////////
template <typename To, typename From>
struct to_impl<To, From, when<
hana::Constant<From>::value &&
is_convertible<typename From::value_type, To>::value
>> : embedding<is_embedded<typename From::value_type, To>::value> {
template <typename X>
static constexpr decltype(auto) apply(X const&)
{ return hana::to<To>(hana::value<X>()); }
};
//////////////////////////////////////////////////////////////////////////
// Foldable -> Sequence
//////////////////////////////////////////////////////////////////////////
template <typename S, typename F>
struct to_impl<S, F, when<
hana::Sequence<S>::value &&
hana::Foldable<F>::value
>> : embedding<Sequence<F>::value> {
template <typename Xs>
static constexpr decltype(auto) apply(Xs&& xs)
{ return hana::unpack(static_cast<Xs&&>(xs), hana::make<S>); }
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CORE_TO_HPP
@@ -0,0 +1,15 @@
/*!
@file
Defines `boost::hana::when` and `boost::hana::when_valid`.
@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_CORE_WHEN_HPP
#define BOOST_HANA_CORE_WHEN_HPP
#include <boost/hana/fwd/core/when.hpp>
#endif // !BOOST_HANA_CORE_WHEN_HPP
@@ -0,0 +1,50 @@
/*!
@file
Defines `boost::hana::count`.
@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_COUNT_HPP
#define BOOST_HANA_COUNT_HPP
#include <boost/hana/fwd/count.hpp>
#include <boost/hana/concept/foldable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/count_if.hpp>
#include <boost/hana/equal.hpp>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs, typename Value>
constexpr auto count_t::operator()(Xs&& xs, Value&& value) const {
using S = typename hana::tag_of<Xs>::type;
using Count = BOOST_HANA_DISPATCH_IF(count_impl<S>,
hana::Foldable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Foldable<S>::value,
"hana::count(xs, value) requires 'xs' to be Foldable");
#endif
return Count::apply(static_cast<Xs&&>(xs), static_cast<Value&&>(value));
}
//! @endcond
template <typename T, bool condition>
struct count_impl<T, when<condition>> : default_ {
template <typename Xs, typename Value>
static constexpr auto apply(Xs&& xs, Value&& value) {
return hana::count_if(static_cast<Xs&&>(xs),
hana::equal.to(static_cast<Value&&>(value)));
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_COUNT_HPP
@@ -0,0 +1,92 @@
/*!
@file
Defines `boost::hana::count_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_COUNT_IF_HPP
#define BOOST_HANA_COUNT_IF_HPP
#include <boost/hana/fwd/count_if.hpp>
#include <boost/hana/concept/foldable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/detail/algorithm.hpp>
#include <boost/hana/detail/fast_and.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/unpack.hpp>
#include <cstddef>
#include <type_traits>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs, typename Pred>
constexpr auto count_if_t::operator()(Xs&& xs, Pred&& pred) const {
using S = typename hana::tag_of<Xs>::type;
using CountIf = BOOST_HANA_DISPATCH_IF(count_if_impl<S>,
hana::Foldable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Foldable<S>::value,
"hana::count_if(xs, pred) requires 'xs' to be Foldable");
#endif
return CountIf::apply(static_cast<Xs&&>(xs),
static_cast<Pred&&>(pred));
}
//! @endcond
namespace detail {
template <typename Pred>
struct count_pred {
Pred pred;
template <typename ...Xs, typename = typename std::enable_if<
detail::fast_and<
Constant<decltype((*pred)(std::declval<Xs&&>()))>::value...
>::value
>::type>
constexpr auto operator()(Xs&& ...xs) const {
constexpr bool results[] = {false, // <-- avoid empty array
static_cast<bool>(hana::value<decltype((*pred)(static_cast<Xs&&>(xs)))>())...
};
constexpr std::size_t total = detail::count(
results, results + sizeof(results), true
);
return hana::size_c<total>;
}
template <typename ...Xs, typename = void, typename = typename std::enable_if<
!detail::fast_and<
Constant<decltype((*pred)(std::declval<Xs&&>()))>::value...
>::value
>::type>
constexpr auto operator()(Xs&& ...xs) const {
std::size_t total = 0;
using Swallow = std::size_t[];
(void)Swallow{0, ((*pred)(static_cast<Xs&&>(xs)) ? ++total : 0)...};
return total;
}
};
}
template <typename T, bool condition>
struct count_if_impl<T, when<condition>> : default_ {
template <typename Xs, typename Pred>
static constexpr decltype(auto) apply(Xs&& xs, Pred&& pred) {
// We use a pointer instead of a reference to avoid a Clang ICE.
return hana::unpack(static_cast<Xs&&>(xs),
detail::count_pred<decltype(&pred)>{&pred}
);
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_COUNT_IF_HPP
@@ -0,0 +1,127 @@
/*!
@file
Defines `boost::hana::cycle`.
@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_CYCLE_HPP
#define BOOST_HANA_CYCLE_HPP
#include <boost/hana/fwd/cycle.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/concat.hpp>
#include <boost/hana/concept/integral_constant.hpp>
#include <boost/hana/concept/monad_plus.hpp>
#include <boost/hana/concept/sequence.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/core/make.hpp>
#include <boost/hana/detail/array.hpp>
#include <boost/hana/empty.hpp>
#include <boost/hana/length.hpp>
#include <cstddef>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN
//! @cond
template <typename Xs, typename N>
constexpr auto cycle_t::operator()(Xs&& xs, N const& n) const {
using M = typename hana::tag_of<Xs>::type;
using Cycle = BOOST_HANA_DISPATCH_IF(cycle_impl<M>,
hana::MonadPlus<M>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::MonadPlus<M>::value,
"hana::cycle(xs, n) requires 'xs' to be a MonadPlus");
static_assert(hana::IntegralConstant<N>::value,
"hana::cycle(xs, n) requires 'n' to be an IntegralConstant");
#endif
static_assert(N::value >= 0,
"hana::cycle(xs, n) requires 'n' to be non-negative");
return Cycle::apply(static_cast<Xs&&>(xs), n);
}
//! @endcond
namespace detail {
template <typename M, std::size_t n, bool = n % 2 == 0>
struct cycle_helper;
template <typename M>
struct cycle_helper<M, 0, true> {
template <typename Xs>
static constexpr auto apply(Xs const&)
{ return hana::empty<M>(); }
};
template <typename M, std::size_t n>
struct cycle_helper<M, n, true> {
template <typename Xs>
static constexpr auto apply(Xs const& xs)
{ return cycle_helper<M, n/2>::apply(hana::concat(xs, xs)); }
};
template <typename M, std::size_t n>
struct cycle_helper<M, n, false> {
template <typename Xs>
static constexpr auto apply(Xs const& xs)
{ return hana::concat(xs, cycle_helper<M, n-1>::apply(xs)); }
};
}
template <typename M, bool condition>
struct cycle_impl<M, when<condition>> : default_ {
template <typename Xs, typename N>
static constexpr auto apply(Xs const& xs, N const&) {
constexpr std::size_t n = N::value;
return detail::cycle_helper<M, n>::apply(xs);
}
};
namespace detail {
template <std::size_t N, std::size_t Len>
struct cycle_indices {
static constexpr auto compute_value() {
detail::array<std::size_t, N * Len> indices{};
// Avoid (incorrect) Clang warning about remainder by zero
// in the loop below.
std::size_t len = Len;
for (std::size_t i = 0; i < N * Len; ++i)
indices[i] = i % len;
return indices;
}
static constexpr auto value = compute_value();
};
}
template <typename S>
struct cycle_impl<S, when<Sequence<S>::value>> {
template <typename Indices, typename Xs, std::size_t ...i>
static constexpr auto cycle_helper(Xs&& xs, std::index_sequence<i...>) {
constexpr auto indices = Indices::value;
(void)indices; // workaround GCC warning when sizeof...(i) == 0
return hana::make<S>(hana::at_c<indices[i]>(xs)...);
}
template <typename Xs, typename N>
static constexpr auto apply(Xs&& xs, N const&) {
constexpr std::size_t n = N::value;
constexpr std::size_t len = decltype(hana::length(xs))::value;
using Indices = detail::cycle_indices<n, len>;
return cycle_helper<Indices>(static_cast<Xs&&>(xs),
std::make_index_sequence<n * len>{});
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_CYCLE_HPP
@@ -0,0 +1,17 @@
/*!
@file
Defines the `BOOST_HANA_DEFINE_STRUCT` macro.
@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_DEFINE_STRUCT_HPP
#define BOOST_HANA_DEFINE_STRUCT_HPP
#include <boost/hana/fwd/define_struct.hpp>
#include <boost/hana/detail/struct_macros.hpp>
#endif // !BOOST_HANA_DEFINE_STRUCT_HPP
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,71 @@
/*!
@file
Defines `boost::hana::detail::index_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_INDEX_IF_HPP
#define BOOST_HANA_DETAIL_INDEX_IF_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
#include <cstddef>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN namespace detail {
template <typename ...T>
struct pack {
static constexpr std::size_t length = sizeof...(T);
};
template <typename T>
struct make_pack;
template <template <typename...> class Template, typename ...T>
struct make_pack<Template<T...>> {
using type = pack<T...>;
};
template <typename T> struct make_pack<T const> : make_pack<T> { };
template <typename T> struct make_pack<T&> : make_pack<T> { };
template <typename T> struct make_pack<T&&> : make_pack<T> { };
//! @ingroup group-details
//! Returns the index of the first element of the `pack<>` that satisfies
//! the predicate, or the size of the pack if there is no such element.
//!
//! @note
//! The predicate must return an `IntegralConstant` that can be explicitly
//! converted to `bool`.
template <typename Pred, typename Ts, typename = when<true>>
struct index_if;
//! @cond
template <typename Pred, typename T, typename ...Ts>
struct index_if<Pred, pack<T, Ts...>, when<static_cast<bool>(decltype(
std::declval<Pred>()(std::declval<T>())
)::value)>> {
static constexpr std::size_t value = 0;
};
template <typename Pred, typename T, typename ...Ts>
struct index_if<Pred, pack<T, Ts...>, when<!static_cast<bool>(decltype(
std::declval<Pred>()(std::declval<T>())
)::value)>> {
static constexpr std::size_t value = 1 + index_if<Pred, pack<Ts...>>::value;
};
template <typename Pred>
struct index_if<Pred, pack<>> {
static constexpr std::size_t value = 0;
};
//! @endcond
} BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_DETAIL_INDEX_IF_HPP
@@ -0,0 +1,245 @@
/*!
@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>
struct integral_constant
: 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,44 @@
/*!
@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::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::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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,106 @@
/*!
@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
//! Macro expanding to the number of arguments it is passed.
//!
//! Specifically, `BOOST_HANA_PP_NARG(x1, ..., xn)` expands to `n`.
//! It is undefined behavior if `n > 64` or if `n == 0`.
#define BOOST_HANA_PP_NARG(...) \
BOOST_HANA_PP_NARG_IMPL(__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,)
#define BOOST_HANA_PP_NARG_IMPL(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63, N, ...) N
//! @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 last argument.
//!
//! This macro can be passed up to 20 arguments.
#define BOOST_HANA_PP_BACK(...) \
BOOST_HANA_PP_BACK_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)
#define BOOST_HANA_PP_BACK_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_BACK_IMPL_, N)(__VA_ARGS__)
#define BOOST_HANA_PP_BACK_IMPL_1(e0) e0
#define BOOST_HANA_PP_BACK_IMPL_2(e0, e1) e1
#define BOOST_HANA_PP_BACK_IMPL_3(e0, e1, e2) e2
#define BOOST_HANA_PP_BACK_IMPL_4(e0, e1, e2, e3) e3
#define BOOST_HANA_PP_BACK_IMPL_5(e0, e1, e2, e3, e4) e4
#define BOOST_HANA_PP_BACK_IMPL_6(e0, e1, e2, e3, e4, e5) e5
#define BOOST_HANA_PP_BACK_IMPL_7(e0, e1, e2, e3, e4, e5, e6) e6
#define BOOST_HANA_PP_BACK_IMPL_8(e0, e1, e2, e3, e4, e5, e6, e7) e7
#define BOOST_HANA_PP_BACK_IMPL_9(e0, e1, e2, e3, e4, e5, e6, e7, e8) e8
#define BOOST_HANA_PP_BACK_IMPL_10(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9
#define BOOST_HANA_PP_BACK_IMPL_11(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10) e10
#define BOOST_HANA_PP_BACK_IMPL_12(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11) e11
#define BOOST_HANA_PP_BACK_IMPL_13(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) e12
#define BOOST_HANA_PP_BACK_IMPL_14(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13) e13
#define BOOST_HANA_PP_BACK_IMPL_15(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14) e14
#define BOOST_HANA_PP_BACK_IMPL_16(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15) e15
#define BOOST_HANA_PP_BACK_IMPL_17(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16) e16
#define BOOST_HANA_PP_BACK_IMPL_18(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17) e17
#define BOOST_HANA_PP_BACK_IMPL_19(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18) e18
#define BOOST_HANA_PP_BACK_IMPL_20(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19) e19
//! @ingroup group-details
//! Expands to all of its arguments, except for the last one.
//!
//! This macro can be given up to 20 arguments.
#define BOOST_HANA_PP_DROP_BACK(...) \
BOOST_HANA_PP_DROP_BACK_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)
#define BOOST_HANA_PP_DROP_BACK_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_DROP_BACK_IMPL_, N)(__VA_ARGS__)
#define BOOST_HANA_PP_DROP_BACK_IMPL_1(e0)
#define BOOST_HANA_PP_DROP_BACK_IMPL_2(e0, e1) e0
#define BOOST_HANA_PP_DROP_BACK_IMPL_3(e0, e1, e2) e0, e1
#define BOOST_HANA_PP_DROP_BACK_IMPL_4(e0, e1, e2, e3) e0, e1, e2
#define BOOST_HANA_PP_DROP_BACK_IMPL_5(e0, e1, e2, e3, e4) e0, e1, e2, e3
#define BOOST_HANA_PP_DROP_BACK_IMPL_6(e0, e1, e2, e3, e4, e5) e0, e1, e2, e3, e4
#define BOOST_HANA_PP_DROP_BACK_IMPL_7(e0, e1, e2, e3, e4, e5, e6) e0, e1, e2, e3, e4, e5
#define BOOST_HANA_PP_DROP_BACK_IMPL_8(e0, e1, e2, e3, e4, e5, e6, e7) e0, e1, e2, e3, e4, e5, e6
#define BOOST_HANA_PP_DROP_BACK_IMPL_9(e0, e1, e2, e3, e4, e5, e6, e7, e8) e0, e1, e2, e3, e4, e5, e6, e7
#define BOOST_HANA_PP_DROP_BACK_IMPL_10(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9) e0, e1, e2, e3, e4, e5, e6, e7, e8
#define BOOST_HANA_PP_DROP_BACK_IMPL_11(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9
#define BOOST_HANA_PP_DROP_BACK_IMPL_12(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10
#define BOOST_HANA_PP_DROP_BACK_IMPL_13(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11
#define BOOST_HANA_PP_DROP_BACK_IMPL_14(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12
#define BOOST_HANA_PP_DROP_BACK_IMPL_15(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13
#define BOOST_HANA_PP_DROP_BACK_IMPL_16(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14
#define BOOST_HANA_PP_DROP_BACK_IMPL_17(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15
#define BOOST_HANA_PP_DROP_BACK_IMPL_18(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16
#define BOOST_HANA_PP_DROP_BACK_IMPL_19(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17
#define BOOST_HANA_PP_DROP_BACK_IMPL_20(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18
//! @ingroup group-details
//! Expands to its first argument.
#define BOOST_HANA_PP_FRONT(...) BOOST_HANA_PP_FRONT_IMPL(__VA_ARGS__, )
#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
@@ -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
@@ -0,0 +1,185 @@
<%#
This is an ERB [1] template file used to generate the
<boost/hana/detail/struct_macros.hpp> header. The maximum
number of members that can be handled by the macros can
be controlled with the 'MAX_NUMBER_OF_MEMBERS' variable,
which can be set when calling ERB to generate the header:
export MAX_NUMBER_OF_MEMBERS=55; erb struct_macros.erb.hpp
'MAX_NUMBER_OF_MEMBERS' must be <= 62, otherwise an error is triggered.
In case 'MAX_NUMBER_OF_MEMBERS' is not specified, it defaults to 40.
[1]: http://en.wikipedia.org/wiki/ERuby
%>
<%
MAX_NUMBER_OF_MEMBERS = (ENV["MAX_NUMBER_OF_MEMBERS"] || 40).to_i
raise "MAX_NUMBER_OF_MEMBERS must be <= 62" if MAX_NUMBER_OF_MEMBERS > 62
%>
/*!
@file
Defines the `BOOST_HANA_DEFINE_STRUCT`, `BOOST_HANA_ADAPT_STRUCT`, and
`BOOST_HANA_ADAPT_ADT` 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)
*/
//////////////////////////////////////////////////////////////////////////////
// THIS FILE IS GENERATED FROM THE <boost/hana/detail/struct_macros.erb.hpp>
// ERB TEMPLATE. DO NOT EDIT THIS FILE DIRECTLY.
//
// THE ERB TEMPLATE CONTAINS INFORMATION ABOUT HOW TO REGENERATE THIS FILE.
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_HANA_DETAIL_STRUCT_MACROS_HPP
#define BOOST_HANA_DETAIL_STRUCT_MACROS_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/preprocessor.hpp>
#include <boost/hana/pair.hpp>
#include <boost/hana/string.hpp>
#include <boost/hana/tuple.hpp>
#include <cstddef>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN namespace struct_detail {
template <typename Memptr, Memptr ptr>
struct member_ptr {
template <typename T>
constexpr decltype(auto) operator()(T&& t) const
{ return static_cast<T&&>(t).*ptr; }
};
constexpr std::size_t strlen(char const* s) {
std::size_t n = 0;
while (*s++ != '\0')
++n;
return n;
}
template <std::size_t n, typename Names, std::size_t ...i>
constexpr auto prepare_member_name_impl(std::index_sequence<i...>) {
return hana::string_c<hana::at_c<n>(Names::get())[i]...>;
}
template <std::size_t n, typename Names>
constexpr auto prepare_member_name() {
constexpr std::size_t len = strlen(hana::at_c<n>(Names::get()));
return prepare_member_name_impl<n, Names>(std::make_index_sequence<len>{});
}
} BOOST_HANA_NAMESPACE_END
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_ADAPT_STRUCT
//////////////////////////////////////////////////////////////////////////////
template <typename ...>
struct BOOST_HANA_ADAPT_STRUCT_must_be_called_in_the_global_namespace;
#define BOOST_HANA_ADAPT_STRUCT(...) \
template <> \
struct BOOST_HANA_ADAPT_STRUCT_must_be_called_in_the_global_namespace<>; \
BOOST_HANA_ADAPT_STRUCT_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)\
static_assert(true, "force the usage of a trailing semicolon") \
/**/
#define BOOST_HANA_ADAPT_STRUCT_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_ADAPT_STRUCT_IMPL_, N)(__VA_ARGS__)
<% (0..MAX_NUMBER_OF_MEMBERS).each do |n| %>
#define BOOST_HANA_ADAPT_STRUCT_IMPL_<%= n+1 %>(TYPE <%= (1..n).map { |i| ", m#{i}" }.join %>) \
namespace boost { namespace hana { \
template <> \
struct accessors_impl<TYPE> { \
static constexpr auto apply() { \
struct member_names { \
static constexpr auto get() { \
return ::boost::hana::make_tuple( \
<%= (1..n).map { |i| "BOOST_HANA_PP_STRINGIZE(m#{i})" }.join(', ') %> \
); \
} \
}; \
return ::boost::hana::make_tuple( \
<%= (1..n).map { |i| "::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<#{i-1}, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::m#{i}), &TYPE::m#{i}>{})" }.join(', ') %>\
); \
} \
}; \
}} \
/**/
<% end %>
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_ADAPT_ADT
//////////////////////////////////////////////////////////////////////////////
template <typename ...>
struct BOOST_HANA_ADAPT_ADT_must_be_called_in_the_global_namespace;
#define BOOST_HANA_ADAPT_ADT(...) \
template <> \
struct BOOST_HANA_ADAPT_ADT_must_be_called_in_the_global_namespace<>; \
BOOST_HANA_ADAPT_ADT_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__) \
static_assert(true, "force the usage of a trailing semicolon") \
/**/
#define BOOST_HANA_ADAPT_ADT_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_ADAPT_ADT_IMPL_, N)(__VA_ARGS__)
<% (0..MAX_NUMBER_OF_MEMBERS).each do |n| %>
#define BOOST_HANA_ADAPT_ADT_IMPL_<%= n+1 %>(TYPE <%= (1..n).map { |i| ", m#{i}" }.join %>) \
namespace boost { namespace hana { \
template <> \
struct accessors_impl<TYPE> { \
template <typename ...> \
static constexpr auto apply() { \
struct member_names { \
static constexpr auto get() { \
return ::boost::hana::make_tuple( \
<%= (1..n).map { |i| "BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_FRONT m#{i})" }.join(', ') %>\
); \
} \
}; \
return ::boost::hana::make_tuple( \
<%= (1..n).map { |i| "::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<#{i-1}, member_names>(), BOOST_HANA_PP_DROP_FRONT m#{i})" }.join(', ') %>\
); \
} \
}; \
}} \
/**/
<% end %>
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_DEFINE_STRUCT
//////////////////////////////////////////////////////////////////////////////
#define BOOST_HANA_DEFINE_STRUCT(...) \
BOOST_HANA_DEFINE_STRUCT_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)
#define BOOST_HANA_DEFINE_STRUCT_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_DEFINE_STRUCT_IMPL_, N)(__VA_ARGS__)
<% (0..MAX_NUMBER_OF_MEMBERS).each do |n| %>
#define BOOST_HANA_DEFINE_STRUCT_IMPL_<%= n+1 %>(TYPE <%= (1..n).map { |i| ", m#{i}" }.join %>) \
<%= (1..n).map { |i| "BOOST_HANA_PP_DROP_BACK m#{i} BOOST_HANA_PP_BACK m#{i};" }.join(' ') %> \
\
struct hana_accessors_impl { \
static constexpr auto apply() { \
struct member_names { \
static constexpr auto get() { \
return ::boost::hana::make_tuple( \
<%= (1..n).map { |i| "BOOST_HANA_PP_STRINGIZE(BOOST_HANA_PP_BACK m#{i})" }.join(', ') %>\
); \
} \
}; \
return ::boost::hana::make_tuple( \
<%= (1..n).map { |i| "::boost::hana::make_pair(::boost::hana::struct_detail::prepare_member_name<#{i-1}, member_names>(), ::boost::hana::struct_detail::member_ptr<decltype(&TYPE::BOOST_HANA_PP_BACK m#{i}), &TYPE::BOOST_HANA_PP_BACK m#{i}>{})" }.join(', ') %>\
); \
} \
} \
/**/
<% end %>
#endif // !BOOST_HANA_DETAIL_STRUCT_MACROS_HPP
File diff suppressed because one or more lines are too long
@@ -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
@@ -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
@@ -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
@@ -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[] = {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
@@ -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

Some files were not shown because too many files have changed in this diff Show More