stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork
This commit is contained in:
@@ -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
Reference in New Issue
Block a user