This commit is contained in:
peranger 2025-01-12 20:40:48 +08:00
parent 904fbf80b1
commit 3dd696ce76
10000 changed files with 1894755 additions and 0 deletions

View File

@ -0,0 +1,40 @@
/*!
@file
Defines operators for Searchables.
Copyright Louis Dionne 2013-2022
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>
namespace boost { namespace hana { 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));
}
};
} }} // end namespace boost::hana
#endif // !BOOST_HANA_DETAIL_OPERATORS_SEARCHABLE_HPP

View File

@ -0,0 +1,39 @@
/*!
@file
Defines generally useful preprocessor macros.
Copyright Louis Dionne 2013-2022
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_HANA_DETAIL_PREPROCESSOR_HPP
#define BOOST_HANA_DETAIL_PREPROCESSOR_HPP
//! @ingroup group-details
//! Expands to the concatenation of its two arguments.
#define BOOST_HANA_PP_CONCAT(x, y) BOOST_HANA_PP_CONCAT_PRIMITIVE(x, y)
#define BOOST_HANA_PP_CONCAT_PRIMITIVE(x, y) x ## y
//! @ingroup group-details
//! Expands to the stringized version of its argument.
#define BOOST_HANA_PP_STRINGIZE(...) BOOST_HANA_PP_STRINGIZE_PRIMITIVE(__VA_ARGS__)
#define BOOST_HANA_PP_STRINGIZE_PRIMITIVE(...) #__VA_ARGS__
//! @ingroup group-details
//! Expands to its first argument.
#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
#define BOOST_HANA_PP_FRONT(...) BOOST_HANA_PP_FRONT_IMPL_I(__VA_ARGS__)
#define BOOST_HANA_PP_FRONT_IMPL_I(...) BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_FRONT_IMPL(__VA_ARGS__, ),)
#else
#define BOOST_HANA_PP_FRONT(...) BOOST_HANA_PP_FRONT_IMPL(__VA_ARGS__, )
#endif
#define BOOST_HANA_PP_FRONT_IMPL(e0, ...) e0
//! @ingroup group-details
//! Expands to all of its arguments, except for the first one.
//!
//! This macro may not be called with less than 2 arguments.
#define BOOST_HANA_PP_DROP_FRONT(e0, ...) __VA_ARGS__
#endif // !BOOST_HANA_DETAIL_PREPROCESSOR_HPP

View File

@ -0,0 +1,36 @@
/*!
@file
Defines a SFINAE-friendly version of `std::common_type`.
Copyright Louis Dionne 2013-2022
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>
namespace boost { namespace hana { 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;
};
} }} // end namespace boost::hana
#endif // !BOOST_HANA_DETAIL_STD_COMMON_TYPE_HPP

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,267 @@
<%#
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.hpp.erb
'MAX_NUMBER_OF_MEMBERS' must be greater than 0. In case 'MAX_NUMBER_OF_MEMBERS'
is not specified, it defaults to 55. To regenerate the default struct macros,
issue the following command from the root of the project:
erb include/boost/hana/detail/struct_macros.hpp.erb > include/boost/hana/detail/struct_macros.hpp
[1]: http://en.wikipedia.org/wiki/ERuby
%>
<%
MAX_NUMBER_OF_MEMBERS = (ENV["MAX_NUMBER_OF_MEMBERS"] || 55).to_i
raise "MAX_NUMBER_OF_MEMBERS must be > 0" if not MAX_NUMBER_OF_MEMBERS > 0
%>
/*!
@file
Defines the `BOOST_HANA_DEFINE_STRUCT`, `BOOST_HANA_ADAPT_STRUCT`, and
`BOOST_HANA_ADAPT_ADT` macros.
Copyright Louis Dionne 2013-2022
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>
namespace boost { namespace hana { 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>{});
}
} }} // end namespace boost::hana
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_PP_NARG
//////////////////////////////////////////////////////////////////////////////
//! @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
//! an error to call this macro with 0 arguments.
#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
# define BOOST_HANA_PP_NARG(...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_NARG_IMPL(__VA_ARGS__, <%= (1..MAX_NUMBER_OF_MEMBERS).to_a.reverse.join(',') %>,),)
#else
# define BOOST_HANA_PP_NARG(...) \
BOOST_HANA_PP_NARG_IMPL(__VA_ARGS__, <%= (1..MAX_NUMBER_OF_MEMBERS).to_a.reverse.join(',') %>,)
#endif
#define BOOST_HANA_PP_NARG_IMPL(<%= (1..MAX_NUMBER_OF_MEMBERS).to_a.map { |i| "e#{i}" }.join(',') %>, N, ...) N
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_PP_BACK
//////////////////////////////////////////////////////////////////////////////
//! @ingroup group-details
//! Expands to its last argument.
#define BOOST_HANA_PP_BACK(...) \
BOOST_HANA_PP_BACK_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)
#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
# define BOOST_HANA_PP_BACK_IMPL(N, ...) BOOST_HANA_PP_BACK_IMPL_I(N, __VA_ARGS__)
# define BOOST_HANA_PP_BACK_IMPL_I(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_BACK_IMPL_, N)(__VA_ARGS__),)
#else
# define BOOST_HANA_PP_BACK_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_BACK_IMPL_, N)(__VA_ARGS__)
#endif
<% (1..MAX_NUMBER_OF_MEMBERS).each do |n| %>
#define BOOST_HANA_PP_BACK_IMPL_<%= n %>(<%= (1..n).to_a.map { |i| "e#{i}" }.join(', ') %>) e<%= n %>
<% end %>
//////////////////////////////////////////////////////////////////////////////
// BOOST_HANA_PP_DROP_BACK
//////////////////////////////////////////////////////////////////////////////
//! @ingroup group-details
//! Expands to all of its arguments, except for the last one.
#define BOOST_HANA_PP_DROP_BACK(...) \
BOOST_HANA_PP_DROP_BACK_IMPL(BOOST_HANA_PP_NARG(__VA_ARGS__), __VA_ARGS__)
#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
# define BOOST_HANA_PP_DROP_BACK_IMPL(N, ...) BOOST_HANA_PP_DROP_BACK_IMPL_I(N, __VA_ARGS__)
# define BOOST_HANA_PP_DROP_BACK_IMPL_I(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_DROP_BACK_IMPL_, N)(__VA_ARGS__),)
#else
# define BOOST_HANA_PP_DROP_BACK_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_DROP_BACK_IMPL_, N)(__VA_ARGS__)
#endif
<% (1..MAX_NUMBER_OF_MEMBERS).each do |n| %>
#define BOOST_HANA_PP_DROP_BACK_IMPL_<%= n %>(<%= (1..n).to_a.map { |i| "e#{i}" }.join(', ') %>)<%= (1..n-1).to_a.map { |i| "e#{i}" }.join(', ') %>
<% 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") \
/**/
#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
# define BOOST_HANA_ADAPT_STRUCT_IMPL(N, ...) BOOST_HANA_ADAPT_STRUCT_IMPL_I(N, __VA_ARGS__)
# define BOOST_HANA_ADAPT_STRUCT_IMPL_I(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_CONCAT(BOOST_HANA_ADAPT_STRUCT_IMPL_, N)(__VA_ARGS__),)
#else
# define BOOST_HANA_ADAPT_STRUCT_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_ADAPT_STRUCT_IMPL_, N)(__VA_ARGS__)
#endif
<% (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") \
/**/
#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
# define BOOST_HANA_ADAPT_ADT_IMPL(N, ...) BOOST_HANA_ADAPT_ADT_IMPL_I(N, __VA_ARGS__)
# define BOOST_HANA_ADAPT_ADT_IMPL_I(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_CONCAT(BOOST_HANA_ADAPT_ADT_IMPL_, N)(__VA_ARGS__),)
#else
# define BOOST_HANA_ADAPT_ADT_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_ADAPT_ADT_IMPL_, N)(__VA_ARGS__)
#endif
<% (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__)
#ifdef BOOST_HANA_WORKAROUND_MSVC_PREPROCESSOR_616033
# define BOOST_HANA_DEFINE_STRUCT_IMPL(N, ...) BOOST_HANA_DEFINE_STRUCT_IMPL_I(N, __VA_ARGS__)
# define BOOST_HANA_DEFINE_STRUCT_IMPL_I(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_PP_CONCAT(BOOST_HANA_DEFINE_STRUCT_IMPL_, N)(__VA_ARGS__),)
#else
# define BOOST_HANA_DEFINE_STRUCT_IMPL(N, ...) \
BOOST_HANA_PP_CONCAT(BOOST_HANA_DEFINE_STRUCT_IMPL_, N)(__VA_ARGS__)
#endif
<% (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

View File

@ -0,0 +1,57 @@
/*!
@file
Defines `boost::hana::detail::type_at`.
Copyright Louis Dionne 2013-2022
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
namespace boost { namespace hana { 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
};
} }} // end namespace boost::hana
#endif // !BOOST_HANA_DETAIL_TYPE_AT_HPP

View File

@ -0,0 +1,145 @@
/*!
@file
Defines `boost::hana::detail::type_foldl1`.
Copyright Louis Dionne 2013-2022
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>
namespace boost { namespace hana { 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...>;
};
} }} // end namespace boost::hana
#endif // !BOOST_HANA_DETAIL_TYPE_FOLDL1_HPP

View File

@ -0,0 +1,149 @@
/*!
@file
Defines `boost::hana::detail::type_foldr1`.
Copyright Louis Dionne 2013-2022
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>
namespace boost { namespace hana { 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...>;
};
} }} // end namespace boost::hana
#endif // !BOOST_HANA_DETAIL_TYPE_FOLDR1_HPP

View File

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

View File

@ -0,0 +1,40 @@
/*!
@file
Defines `boost::hana::detail::variadic::at`.
Copyright Louis Dionne 2013-2022
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>
namespace boost { namespace hana { 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>
BOOST_HANA_INLINE_VARIABLE constexpr at_type<n> at{};
}} }} // end namespace boost::hana
#endif // !BOOST_HANA_DETAIL_VARIADIC_AT_HPP

View File

@ -0,0 +1,47 @@
/*!
@file
Defines `boost::hana::detail::variadic::drop_into`.
Copyright Louis Dionne 2013-2022
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_HANA_DETAIL_VARIADIC_DROP_INTO_HPP
#define BOOST_HANA_DETAIL_VARIADIC_DROP_INTO_HPP
#include <boost/hana/config.hpp>
#include <cstddef>
#include <utility>
namespace boost { namespace hana { namespace detail { namespace variadic {
template <std::size_t n, typename F, typename = std::make_index_sequence<n>>
struct dropper;
template <std::size_t n, typename F, std::size_t ...ignore>
struct dropper<n, F, std::index_sequence<ignore...>> {
F f;
template <typename ...Rest>
constexpr auto go(decltype(ignore, (void*)0)..., Rest ...rest) const
{ return f(*rest...); }
template <typename ...Xs>
constexpr auto operator()(Xs ...xs) const
{ return go(&xs...); }
};
template <std::size_t n>
struct make_dropper {
template <typename F>
constexpr auto operator()(F f) const
{ return dropper<n, decltype(f)>{f}; }
};
template <std::size_t n>
BOOST_HANA_INLINE_VARIABLE constexpr make_dropper<n> drop_into{};
}} }} // end namespace boost::hana
#endif // !BOOST_HANA_DETAIL_VARIADIC_DROP_INTO_HPP

View File

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

View File

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

View File

@ -0,0 +1,27 @@
/*!
@file
Defines `boost::hana::detail::variadic::reverse_apply`.
Copyright Louis Dionne 2013-2022
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_HPP
#define BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/variadic/reverse_apply/unrolled.hpp>
namespace boost { namespace hana { namespace detail { namespace variadic {
BOOST_HANA_INLINE_VARIABLE BOOST_HANA_CONSTEXPR_LAMBDA auto reverse_apply =
[](auto&& f, auto&& ...x) -> decltype(auto) {
return detail::variadic::reverse_apply_unrolled(
static_cast<decltype(f)>(f),
static_cast<decltype(x)>(x)...
);
};
}} }} // end namespace boost::hana
#endif // !BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_HPP

View File

@ -0,0 +1,41 @@
/*!
@file
Defines `boost::hana::detail::variadic::reverse_apply_flat`.
Copyright Louis Dionne 2013-2022
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_FLAT_HPP
#define BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_FLAT_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/variadic/at.hpp>
#include <utility>
namespace boost { namespace hana { namespace detail { namespace variadic {
template <int ...i, typename F, typename ...X>
constexpr decltype(auto)
reverse_apply_flat_helper(std::integer_sequence<int, i...>, F&& f, X&& ...x)
{
return static_cast<F&&>(f)(
detail::variadic::at<sizeof...(x) - i - 1>(
static_cast<X&&>(x)...
)...
);
}
template <typename F, typename ...X>
constexpr decltype(auto) reverse_apply_flat(F&& f, X&& ...x) {
return reverse_apply_flat_helper(
std::make_integer_sequence<int, sizeof...(x)>{},
static_cast<F&&>(f),
static_cast<X&&>(x)...
);
}
}} }} // end namespace boost::hana
#endif // !BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_FLAT_HPP

View File

@ -0,0 +1,86 @@
/*!
@file
Defines `boost::hana::detail::variadic::reverse_apply_unrolled`.
Copyright Louis Dionne 2013-2022
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_UNROLLED_HPP
#define BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_UNROLLED_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/functional/reverse_partial.hpp>
namespace boost { namespace hana { namespace detail { namespace variadic {
struct reverse_apply_unrolled_impl {
template <typename F>
constexpr decltype(auto) operator()(F&& f) const {
return static_cast<F&&>(f)();
}
template <typename F, typename X1>
constexpr decltype(auto) operator()(F&& f, X1&& x1) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1)
);
}
template <typename F, typename X1, typename X2>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2) const {
return static_cast<F&&>(f)(
static_cast<X2&&>(x2),
static_cast<X1&&>(x1)
);
}
template <typename F, typename X1, typename X2, typename X3>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3) const {
return static_cast<F&&>(f)(
static_cast<X3&&>(x3),
static_cast<X2&&>(x2),
static_cast<X1&&>(x1)
);
}
template <typename F, typename X1, typename X2, typename X3, typename X4>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4) const {
return static_cast<F&&>(f)(
static_cast<X4&&>(x4),
static_cast<X3&&>(x3),
static_cast<X2&&>(x2),
static_cast<X1&&>(x1)
);
}
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5) const {
return static_cast<F&&>(f)(
static_cast<X5&&>(x5),
static_cast<X4&&>(x4),
static_cast<X3&&>(x3),
static_cast<X2&&>(x2),
static_cast<X1&&>(x1)
);
}
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename ...Xn>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, Xn&& ...xn) const {
return (*this)(hana::reverse_partial(
static_cast<F&&>(f)
, static_cast<X6&&>(x6)
, static_cast<X5&&>(x5)
, static_cast<X4&&>(x4)
, static_cast<X3&&>(x3)
, static_cast<X2&&>(x2)
, static_cast<X1&&>(x1)
), static_cast<Xn&&>(xn)...);
}
};
BOOST_HANA_INLINE_VARIABLE constexpr reverse_apply_unrolled_impl reverse_apply_unrolled{};
}} }} // end namespace boost::hana
#endif // !BOOST_HANA_DETAIL_VARIADIC_REVERSE_APPLY_UNROLLED_HPP

View File

@ -0,0 +1,153 @@
/*!
@file
Defines `boost::hana::detail::variadic::split_at`.
Copyright Louis Dionne 2013-2022
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_HANA_DETAIL_VARIADIC_SPLIT_AT_HPP
#define BOOST_HANA_DETAIL_VARIADIC_SPLIT_AT_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/functional/partial.hpp>
#include <boost/hana/functional/reverse_partial.hpp>
#include <cstddef>
namespace boost { namespace hana { namespace detail { namespace variadic {
template <std::size_t n>
struct split_at_t {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8, Xs&& ...xs) const {
return split_at_t<n - 8>{}(
hana::partial(static_cast<F&&>(f),
static_cast<X1&&>(x1),
static_cast<X2&&>(x2),
static_cast<X3&&>(x3),
static_cast<X4&&>(x4),
static_cast<X5&&>(x5),
static_cast<X6&&>(x6),
static_cast<X7&&>(x7),
static_cast<X8&&>(x8)
),
static_cast<Xs&&>(xs)...
);
}
};
template <>
struct split_at_t<0> {
template <typename F, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, Xs&& ...xs) const {
return static_cast<F&&>(f)()(static_cast<Xs&&>(xs)...);
}
};
template <>
struct split_at_t<1> {
template <typename F, typename X1, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, Xs&& ...xs) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1)
)(static_cast<Xs&&>(xs)...);
}
};
template <>
struct split_at_t<2> {
template <typename F, typename X1, typename X2, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, Xs&& ...xs) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1),
static_cast<X2&&>(x2)
)(static_cast<Xs&&>(xs)...);
}
};
template <>
struct split_at_t<3> {
template <typename F, typename X1, typename X2, typename X3, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, Xs&& ...xs) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1),
static_cast<X2&&>(x2),
static_cast<X3&&>(x3)
)(static_cast<Xs&&>(xs)...);
}
};
template <>
struct split_at_t<4> {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, Xs&& ...xs) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1),
static_cast<X2&&>(x2),
static_cast<X3&&>(x3),
static_cast<X4&&>(x4)
)(static_cast<Xs&&>(xs)...);
}
};
template <>
struct split_at_t<5> {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, Xs&& ...xs) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1),
static_cast<X2&&>(x2),
static_cast<X3&&>(x3),
static_cast<X4&&>(x4),
static_cast<X5&&>(x5)
)(static_cast<Xs&&>(xs)...);
}
};
template <>
struct split_at_t<6> {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, Xs&& ...xs) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1),
static_cast<X2&&>(x2),
static_cast<X3&&>(x3),
static_cast<X4&&>(x4),
static_cast<X5&&>(x5),
static_cast<X6&&>(x6)
)(static_cast<Xs&&>(xs)...);
}
};
template <>
struct split_at_t<7> {
template <typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, Xs&& ...xs) const {
return static_cast<F&&>(f)(
static_cast<X1&&>(x1),
static_cast<X2&&>(x2),
static_cast<X3&&>(x3),
static_cast<X4&&>(x4),
static_cast<X5&&>(x5),
static_cast<X6&&>(x6),
static_cast<X7&&>(x7)
)(static_cast<Xs&&>(xs)...);
}
};
template <std::size_t n>
struct _makesplit_at_t {
template <typename ...Xs>
constexpr decltype(auto) operator()(Xs&& ...xs) const {
return hana::reverse_partial(split_at_t<n>{},
static_cast<Xs&&>(xs)...);
}
};
template <std::size_t n>
BOOST_HANA_INLINE_VARIABLE constexpr _makesplit_at_t<n> split_at{};
}} }} // end namespace boost::hana
#endif // !BOOST_HANA_DETAIL_VARIADIC_SPLIT_AT_HPP

View File

@ -0,0 +1,51 @@
/*!
@file
Defines `boost::hana::detail::variadic::take`.
Copyright Louis Dionne 2013-2022
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_HANA_DETAIL_VARIADIC_TAKE_HPP
#define BOOST_HANA_DETAIL_VARIADIC_TAKE_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/variadic/split_at.hpp>
#include <boost/hana/functional/always.hpp>
#include <boost/hana/functional/reverse_partial.hpp>
#include <cstddef>
namespace boost { namespace hana { namespace detail { namespace variadic {
struct take_impl2 {
template <typename F, typename ...Xs>
constexpr decltype(auto) operator()(F&& f, Xs&& ...xs) const {
return static_cast<F&&>(f)(static_cast<Xs&&>(xs)...);
}
};
struct take_impl1 {
template <typename ...Xs>
constexpr auto operator()(Xs&& ...xs) const {
return hana::always(
reverse_partial(take_impl2{},
static_cast<Xs&&>(xs)...)
);
}
};
template <std::size_t n>
struct take_t {
template <typename ...Xs>
constexpr decltype(auto) operator()(Xs&& ...xs) const {
return variadic::split_at<n>(static_cast<Xs&&>(xs)...)(take_impl1{});
}
};
template <std::size_t n>
BOOST_HANA_INLINE_VARIABLE constexpr take_t<n> take{};
}} }} // end namespace boost::hana
#endif // !BOOST_HANA_DETAIL_VARIADIC_TAKE_HPP

View File

@ -0,0 +1,21 @@
/*!
@file
Defines an equivalent to the proposed `std::void_t`.
Copyright Louis Dionne 2013-2022
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_HANA_DETAIL_VOID_T_HPP
#define BOOST_HANA_DETAIL_VOID_T_HPP
#include <boost/hana/config.hpp>
namespace boost { namespace hana { namespace detail {
template <typename ...>
using void_t = void;
} }} // end namespace boost::hana
#endif // !BOOST_HANA_DETAIL_VOID_T_HPP

View File

@ -0,0 +1,33 @@
/*!
@file
Defines `boost::hana::detail::wrong`.
Copyright Louis Dionne 2013-2022
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_HANA_DETAIL_WRONG_HPP
#define BOOST_HANA_DETAIL_WRONG_HPP
#include <boost/hana/config.hpp>
#include <type_traits>
namespace boost { namespace hana { namespace detail {
//! @ingroup group-detail
//! Equivalent to a type-dependent `std::false_type`.
//!
//! This is useful for making a static assertion that would otherwise
//! always fire up dependent on some template parameters.
//!
//!
//! Example
//! -------
//! @include example/detail/wrong.cpp
template <typename ...>
struct wrong : std::false_type { };
} }} // end namespace boost::hana
#endif // !BOOST_HANA_DETAIL_WRONG_HPP

View File

@ -0,0 +1,40 @@
/*!
@file
Defines `boost::hana::difference`.
Copyright Louis Dionne 2013-2022
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_DIFFERENCE_HPP
#define BOOST_HANA_DIFFERENCE_HPP
#include <boost/hana/fwd/difference.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/erase_key.hpp>
namespace boost { namespace hana {
//! @cond
template <typename Xs, typename Ys>
constexpr auto difference_t::operator()(Xs&& xs, Ys&& ys) const {
using S = typename hana::tag_of<Xs>::type;
using Difference = BOOST_HANA_DISPATCH_IF(difference_impl<S>,
true
);
return Difference::apply(static_cast<Xs&&>(xs), static_cast<Ys&&>(ys));
}
//! @endcond
template <typename S, bool condition>
struct difference_impl<S, when<condition>> : default_ {
template <typename ...Args>
static constexpr auto apply(Args&& ...) = delete;
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_DIFFERENCE_HPP

View File

@ -0,0 +1,107 @@
/*!
@file
Defines `boost::hana::div`.
Copyright Louis Dionne 2013-2022
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_DIV_HPP
#define BOOST_HANA_DIV_HPP
#include <boost/hana/fwd/div.hpp>
#include <boost/hana/concept/constant.hpp>
#include <boost/hana/concept/euclidean_ring.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/to.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/detail/canonical_constant.hpp>
#include <boost/hana/detail/has_common_embedding.hpp>
#include <boost/hana/value.hpp>
#include <type_traits>
namespace boost { namespace hana {
//! @cond
template <typename X, typename Y>
constexpr decltype(auto) div_t::operator()(X&& x, Y&& y) const {
using T = typename hana::tag_of<X>::type;
using U = typename hana::tag_of<Y>::type;
using Div = BOOST_HANA_DISPATCH_IF(decltype(div_impl<T, U>{}),
hana::EuclideanRing<T>::value &&
hana::EuclideanRing<U>::value &&
!is_default<div_impl<T, U>>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::EuclideanRing<T>::value,
"hana::div(x, y) requires 'x' to be an EuclideanRing");
static_assert(hana::EuclideanRing<U>::value,
"hana::div(x, y) requires 'y' to be an EuclideanRing");
static_assert(!is_default<div_impl<T, U>>::value,
"hana::div(x, y) requires 'x' and 'y' to be embeddable "
"in a common EuclideanRing");
#endif
return Div::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
}
//! @endcond
template <typename T, typename U, bool condition>
struct div_impl<T, U, when<condition>> : default_ {
template <typename ...Args>
static constexpr auto apply(Args&& ...) = delete;
};
// Cross-type overload
template <typename T, typename U>
struct div_impl<T, U, when<
detail::has_nontrivial_common_embedding<EuclideanRing, T, U>::value
>> {
using C = typename common<T, U>::type;
template <typename X, typename Y>
static constexpr decltype(auto) apply(X&& x, Y&& y) {
return hana::div(hana::to<C>(static_cast<X&&>(x)),
hana::to<C>(static_cast<Y&&>(y)));
}
};
//////////////////////////////////////////////////////////////////////////
// Model for integral data types
//////////////////////////////////////////////////////////////////////////
template <typename T>
struct div_impl<T, T, when<std::is_integral<T>::value &&
!std::is_same<T, bool>::value>> {
template <typename X, typename Y>
static constexpr decltype(auto) apply(X&& x, Y&& y)
{ return static_cast<X&&>(x) / static_cast<Y&&>(y); }
};
//////////////////////////////////////////////////////////////////////////
// Model for Constants over an EuclideanRing
//////////////////////////////////////////////////////////////////////////
namespace detail {
template <typename C, typename X, typename Y>
struct constant_from_div {
static constexpr auto value = hana::div(hana::value<X>(), hana::value<Y>());
using hana_tag = detail::CanonicalConstant<typename C::value_type>;
};
}
template <typename C>
struct div_impl<C, C, when<
hana::Constant<C>::value &&
EuclideanRing<typename C::value_type>::value
>> {
template <typename X, typename Y>
static constexpr decltype(auto) apply(X const&, Y const&)
{ return hana::to<C>(detail::constant_from_div<C, X, Y>{}); }
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_DIV_HPP

View File

@ -0,0 +1,75 @@
/*!
@file
Defines `boost::hana::drop_back`.
Copyright Louis Dionne 2013-2022
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_DROP_BACK_HPP
#define BOOST_HANA_DROP_BACK_HPP
#include <boost/hana/fwd/drop_back.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/concept/integral_constant.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/integral_constant.hpp>
#include <boost/hana/length.hpp>
#include <cstddef>
#include <utility>
namespace boost { namespace hana {
//! @cond
template <typename Xs, typename N>
constexpr auto drop_back_t::operator()(Xs&& xs, N const& n) const {
using S = typename hana::tag_of<Xs>::type;
using DropBack = BOOST_HANA_DISPATCH_IF(drop_back_impl<S>,
hana::Sequence<S>::value &&
hana::IntegralConstant<N>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Sequence<S>::value,
"hana::drop_back(xs, n) requires 'xs' to be a Sequence");
static_assert(hana::IntegralConstant<N>::value,
"hana::drop_back(xs, n) requires 'n' to be an IntegralConstant");
#endif
static_assert(N::value >= 0,
"hana::drop_back(xs, n) requires 'n' to be non-negative");
return DropBack::apply(static_cast<Xs&&>(xs), n);
}
template <typename Xs>
constexpr auto drop_back_t::operator()(Xs&& xs) const {
return (*this)(static_cast<Xs&&>(xs), hana::size_c<1>);
}
//! @endcond
template <typename S, bool condition>
struct drop_back_impl<S, when<condition>> : default_ {
template <typename Xs, std::size_t ...n>
static constexpr auto drop_back_helper(Xs&& xs, std::index_sequence<n...>) {
return hana::make<S>(hana::at_c<n>(static_cast<Xs&&>(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;
return drop_back_helper(static_cast<Xs&&>(xs),
std::make_index_sequence<(n > len ? 0 : len - n)>{});
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_DROP_BACK_HPP

View File

@ -0,0 +1,57 @@
/*!
@file
Defines `boost::hana::drop_front`.
Copyright Louis Dionne 2013-2022
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_DROP_FRONT_HPP
#define BOOST_HANA_DROP_FRONT_HPP
#include <boost/hana/fwd/drop_front.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/core/tag_of.hpp>
#include <boost/hana/integral_constant.hpp>
namespace boost { namespace hana {
//! @cond
template <typename Xs, typename N>
constexpr auto drop_front_t::operator()(Xs&& xs, N const& n) const {
using It = typename hana::tag_of<Xs>::type;
using DropFront = BOOST_HANA_DISPATCH_IF(drop_front_impl<It>,
hana::Iterable<It>::value &&
hana::IntegralConstant<N>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Iterable<It>::value,
"hana::drop_front(xs, n) requires 'xs' to be an Iterable");
static_assert(hana::IntegralConstant<N>::value,
"hana::drop_front(xs, n) requires 'n' to be an IntegralConstant");
#endif
return DropFront::apply(static_cast<Xs&&>(xs), n);
}
template <typename Xs>
constexpr auto drop_front_t::operator()(Xs&& xs) const {
return (*this)(static_cast<Xs&&>(xs), hana::size_t<1>{});
}
//! @endcond
template <typename It, bool condition>
struct drop_front_impl<It, when<condition>> : default_ {
template <typename Xs, typename N>
static constexpr auto apply(Xs&&, N const&) = delete;
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_DROP_FRONT_HPP

View File

@ -0,0 +1,85 @@
/*!
@file
Defines `boost::hana::drop_front_exactly`.
Copyright Louis Dionne 2013-2022
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_DROP_FRONT_EXACTLY_HPP
#define BOOST_HANA_DROP_FRONT_EXACTLY_HPP
#include <boost/hana/fwd/drop_front_exactly.hpp>
#include <boost/hana/bool.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/drop_front.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/is_empty.hpp>
namespace boost { namespace hana {
//! @cond
template <typename Xs, typename N>
constexpr auto drop_front_exactly_t::operator()(Xs&& xs, N const& n) const {
using It = typename hana::tag_of<Xs>::type;
using DropFrontExactly = BOOST_HANA_DISPATCH_IF(drop_front_exactly_impl<It>,
hana::Iterable<It>::value &&
hana::IntegralConstant<N>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Iterable<It>::value,
"hana::drop_front_exactly(xs, n) requires 'xs' to be an Iterable");
static_assert(hana::IntegralConstant<N>::value,
"hana::drop_front_exactly(xs, n) requires 'n' to be an IntegralConstant");
#endif
static_assert(N::value >= 0,
"hana::drop_front_exactly(xs, n) requires 'n' to be non-negative");
return DropFrontExactly::apply(static_cast<Xs&&>(xs), n);
}
template <typename Xs>
constexpr auto drop_front_exactly_t::operator()(Xs&& xs) const {
return (*this)(static_cast<Xs&&>(xs), hana::size_c<1>);
}
//! @endcond
namespace detail {
template <typename Xs, typename N>
constexpr void check_dfe_overflow(Xs const& xs, N const&, hana::true_) {
constexpr bool n_overflew_length = decltype(
hana::is_empty(hana::drop_front(xs, hana::size_c<N::value - 1>))
)::value;
static_assert(!n_overflew_length,
"hana::drop_front_exactly(xs, n) requires 'n' to be less than or "
"equal to the number of elements in 'xs'");
}
template <typename Xs, typename N>
constexpr void check_dfe_overflow(Xs const&, N const&, hana::false_) { }
}
template <typename It, bool condition>
struct drop_front_exactly_impl<It, when<condition>> : default_ {
template <typename Xs, typename N>
static constexpr auto apply(Xs&& xs, N const& n) {
auto result = hana::drop_front(static_cast<Xs&&>(xs), n);
constexpr bool check_for_overflow =
decltype(hana::is_empty(result))::value && N::value != 0;
detail::check_dfe_overflow(xs, n, hana::bool_c<check_for_overflow>);
return result; // NRVO applied
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_DROP_FRONT_EXACTLY_HPP

View File

@ -0,0 +1,93 @@
/*!
@file
Defines `boost::hana::drop_while`.
Copyright Louis Dionne 2013-2022
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_DROP_WHILE_HPP
#define BOOST_HANA_DROP_WHILE_HPP
#include <boost/hana/fwd/drop_while.hpp>
#include <boost/hana/concept/foldable.hpp>
#include <boost/hana/concept/iterable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/detail/first_unsatisfied_index.hpp>
#include <boost/hana/drop_front.hpp>
#include <boost/hana/eval_if.hpp>
#include <boost/hana/front.hpp>
#include <boost/hana/is_empty.hpp>
#include <boost/hana/lazy.hpp>
namespace boost { namespace hana {
//! @cond
template <typename Xs, typename Pred>
constexpr auto drop_while_t::operator()(Xs&& xs, Pred&& pred) const {
using It = typename hana::tag_of<Xs>::type;
using DropWhile = BOOST_HANA_DISPATCH_IF(drop_while_impl<It>,
hana::Iterable<It>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Iterable<It>::value,
"hana::drop_while(xs, pred) requires 'xs' to be an Iterable");
#endif
return DropWhile::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
}
//! @endcond
namespace iterable_detail {
struct drop_while_helper {
struct next {
template <typename Xs, typename Pred>
constexpr decltype(auto) operator()(Xs&& xs, Pred&& pred) const {
return hana::drop_while(
hana::drop_front(static_cast<Xs&&>(xs)),
static_cast<Pred&&>(pred)
);
}
};
template <typename Xs, typename Pred>
constexpr decltype(auto) operator()(Xs&& xs, Pred&& pred) const {
return hana::eval_if(pred(hana::front(xs)),
hana::make_lazy(next{})(xs, pred),
hana::make_lazy(xs)
);
}
};
}
template <typename It, bool condition>
struct drop_while_impl<It, when<condition>> : default_ {
template <typename Xs, typename Pred>
static constexpr auto apply(Xs&& xs, Pred&& pred) {
return hana::eval_if(hana::is_empty(xs),
hana::make_lazy(xs),
hana::make_lazy(iterable_detail::drop_while_helper{})(
xs, static_cast<Pred&&>(pred))
);
}
};
template <typename S>
struct drop_while_impl<S, when<hana::Foldable<S>::value>> {
template <typename Xs, typename Pred>
static constexpr auto apply(Xs&& xs, Pred&&) {
using FirstUnsatisfied = decltype(
hana::unpack(static_cast<Xs&&>(xs),
detail::first_unsatisfied_index<Pred&&>{})
);
return hana::drop_front(static_cast<Xs&&>(xs),
FirstUnsatisfied{});
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_DROP_WHILE_HPP

View File

@ -0,0 +1,48 @@
/*!
@file
Defines `boost::hana::duplicate`.
Copyright Louis Dionne 2013-2022
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_DUPLICATE_HPP
#define BOOST_HANA_DUPLICATE_HPP
#include <boost/hana/fwd/duplicate.hpp>
#include <boost/hana/concept/comonad.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/extend.hpp>
#include <boost/hana/functional/id.hpp>
namespace boost { namespace hana {
//! @cond
template <typename W_>
constexpr decltype(auto) duplicate_t::operator()(W_&& w) const {
using W = typename hana::tag_of<W_>::type;
using Duplicate = BOOST_HANA_DISPATCH_IF(duplicate_impl<W>,
hana::Comonad<W>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Comonad<W>::value,
"hana::duplicate(w) requires 'w' to be a Comonad");
#endif
return Duplicate::apply(static_cast<W_&&>(w));
}
//! @endcond
template <typename W, bool condition>
struct duplicate_impl<W, when<condition>> : default_ {
template <typename X>
static constexpr decltype(auto) apply(X&& x)
{ return hana::extend(static_cast<X&&>(x), hana::id); }
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_DUPLICATE_HPP

View File

@ -0,0 +1,53 @@
/*!
@file
Defines `boost::hana::empty`.
Copyright Louis Dionne 2013-2022
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_EMPTY_HPP
#define BOOST_HANA_EMPTY_HPP
#include <boost/hana/fwd/empty.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>
namespace boost { namespace hana {
//! @cond
template <typename M>
constexpr auto empty_t<M>::operator()() const {
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::MonadPlus<M>::value,
"hana::empty<M>() requires 'M' to be a MonadPlus");
#endif
using Empty = BOOST_HANA_DISPATCH_IF(empty_impl<M>,
hana::MonadPlus<M>::value
);
return Empty::apply();
}
//! @endcond
template <typename M, bool condition>
struct empty_impl<M, when<condition>> : default_ {
template <typename ...Args>
static constexpr auto apply(Args&& ...) = delete;
};
template <typename S>
struct empty_impl<S, when<Sequence<S>::value>> {
static constexpr auto apply() {
return hana::make<S>();
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EMPTY_HPP

View File

@ -0,0 +1,206 @@
/*!
@file
Defines `boost::hana::equal`.
Copyright Louis Dionne 2013-2022
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_EQUAL_HPP
#define BOOST_HANA_EQUAL_HPP
#include <boost/hana/fwd/equal.hpp>
#include <boost/hana/accessors.hpp>
#include <boost/hana/all_of.hpp>
#include <boost/hana/and.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/bool.hpp>
#include <boost/hana/concept/comparable.hpp>
#include <boost/hana/concept/constant.hpp>
#include <boost/hana/concept/product.hpp>
#include <boost/hana/concept/sequence.hpp>
#include <boost/hana/concept/struct.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/common.hpp>
#include <boost/hana/core/to.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/detail/concepts.hpp>
#include <boost/hana/detail/has_common_embedding.hpp>
#include <boost/hana/detail/nested_to.hpp> // required by fwd decl
#include <boost/hana/first.hpp>
#include <boost/hana/if.hpp>
#include <boost/hana/length.hpp>
#include <boost/hana/second.hpp>
#include <boost/hana/value.hpp>
#include <cstddef>
namespace boost { namespace hana {
//! @cond
template <typename X, typename Y>
constexpr auto equal_t::operator()(X&& x, Y&& y) const {
using T = typename hana::tag_of<X>::type;
using U = typename hana::tag_of<Y>::type;
using Equal = equal_impl<T, U>;
return Equal::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
}
//! @endcond
template <typename T, typename U, bool condition>
struct equal_impl<T, U, when<condition>> : default_ {
template <typename X, typename Y>
static constexpr auto apply(X const&, Y const&) {
// Delay the static_assert by ensuring T_ is dependent.
using T_ = typename hana::tag_of<X>::type;
static_assert(!hana::is_convertible<T_, U>::value &&
!hana::is_convertible<U, T_>::value,
"No default implementation of hana::equal is provided for related "
"types that can't be safely embedded into a common type, because "
"those are most likely programming errors. If this is really what "
"you want, you can manually convert both objects to a common "
"Comparable type before performing the comparison. If you think "
"you have made your types Comparable but you see this, perhaps you "
"forgot to define some of the necessary methods for an automatic "
"model of Comparable to kick in. A possible culprit is defining "
"'operator==' but not 'operator!='.");
return hana::false_c;
}
};
// Cross-type overload
template <typename T, typename U>
struct equal_impl<T, U, when<
detail::has_nontrivial_common_embedding<Comparable, T, U>::value &&
!detail::EqualityComparable<T, U>::value
>> {
using C = typename hana::common<T, U>::type;
template <typename X, typename Y>
static constexpr auto apply(X&& x, Y&& y) {
return hana::equal(hana::to<C>(static_cast<X&&>(x)),
hana::to<C>(static_cast<Y&&>(y)));
}
};
//////////////////////////////////////////////////////////////////////////
// Model for EqualityComparable data types
//////////////////////////////////////////////////////////////////////////
template <typename T, typename U>
struct equal_impl<T, U, when<detail::EqualityComparable<T, U>::value>> {
template <typename X, typename Y>
static constexpr auto apply(X&& x, Y&& y)
{ return static_cast<X&&>(x) == static_cast<Y&&>(y); }
};
//////////////////////////////////////////////////////////////////////////
// Model for Constants wrapping a Comparable
//////////////////////////////////////////////////////////////////////////
template <typename C>
struct equal_impl<C, C, when<
hana::Constant<C>::value &&
Comparable<typename C::value_type>::value
>> {
template <typename X, typename Y>
static constexpr auto apply(X const&, Y const&) {
constexpr auto eq = hana::equal(hana::value<X>(), hana::value<Y>());
constexpr bool truth_value = hana::if_(eq, true, false);
return hana::bool_<truth_value>{};
}
};
//////////////////////////////////////////////////////////////////////////
// Comparable for Products
//////////////////////////////////////////////////////////////////////////
template <typename T, typename U>
struct equal_impl<T, U, when<hana::Product<T>::value && hana::Product<U>::value>> {
template <typename X, typename Y>
static constexpr auto apply(X const& x, Y const& y) {
return hana::and_(
hana::equal(hana::first(x), hana::first(y)),
hana::equal(hana::second(x), hana::second(y))
);
}
};
//////////////////////////////////////////////////////////////////////////
// Comparable for Sequences
//////////////////////////////////////////////////////////////////////////
namespace detail {
template <typename Xs, typename Ys, std::size_t Length>
struct compare_finite_sequences {
Xs const& xs;
Ys const& ys;
template <std::size_t i>
constexpr auto apply(hana::false_, hana::true_) const {
return compare_finite_sequences::apply<i+1>(
hana::bool_<i+1 == Length>{},
hana::if_(hana::equal(hana::at_c<i>(xs), hana::at_c<i>(ys)),
hana::true_c, hana::false_c)
);
}
template <std::size_t i>
constexpr auto apply(hana::false_, hana::false_) const
{ return hana::false_c; }
template <std::size_t i, typename Result>
constexpr auto apply(hana::true_, Result r) const
{ return r; }
template <std::size_t i>
constexpr bool apply(hana::false_, bool b) const {
return b && compare_finite_sequences::apply<i+1>(
hana::bool_<i+1 == Length>{},
hana::if_(hana::equal(hana::at_c<i>(xs), hana::at_c<i>(ys)),
hana::true_c, hana::false_c)
);
}
};
}
template <typename T, typename U>
struct equal_impl<T, U, when<Sequence<T>::value && hana::Sequence<U>::value>> {
template <typename Xs, typename Ys>
static constexpr auto apply(Xs const& xs, Ys const& ys) {
constexpr std::size_t xs_size = decltype(hana::length(xs))::value;
constexpr std::size_t ys_size = decltype(hana::length(ys))::value;
detail::compare_finite_sequences<Xs, Ys, xs_size> comp{xs, ys};
return comp.template apply<0>(hana::bool_<xs_size == 0>{},
hana::bool_<xs_size == ys_size>{});
}
};
namespace detail {
template <typename X, typename Y>
struct compare_struct_members {
X const& x;
Y const& y;
template <typename Member>
constexpr auto operator()(Member&& member) const {
auto accessor = hana::second(static_cast<Member&&>(member));
return hana::equal(accessor(x), accessor(y));
}
};
}
template <typename S>
struct equal_impl<S, S, when<
hana::Struct<S>::value &&
!detail::EqualityComparable<S, S>::value
>> {
template <typename X, typename Y>
static constexpr auto apply(X const& x, Y const& y) {
return hana::all_of(hana::accessors<S>(),
detail::compare_struct_members<X, Y>{x, y});
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EQUAL_HPP

View File

@ -0,0 +1,37 @@
/*!
@file
Defines `boost::hana::erase_key`.
Copyright Louis Dionne 2013-2022
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_ERASE_KEY_HPP
#define BOOST_HANA_ERASE_KEY_HPP
#include <boost/hana/fwd/erase_key.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
namespace boost { namespace hana {
//! @cond
template <typename Set, typename ...Args>
constexpr decltype(auto) erase_key_t::operator()(Set&& set, Args&& ...args) const {
return erase_key_impl<typename hana::tag_of<Set>::type>::apply(
static_cast<Set&&>(set),
static_cast<Args&&>(args)...
);
}
//! @endcond
template <typename T, bool condition>
struct erase_key_impl<T, when<condition>> : default_ {
template <typename ...Args>
static constexpr auto apply(Args&& ...) = delete;
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_ERASE_KEY_HPP

View File

@ -0,0 +1,57 @@
/*!
@file
Defines `boost::hana::eval`.
Copyright Louis Dionne 2013-2022
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_EVAL_HPP
#define BOOST_HANA_EVAL_HPP
#include <boost/hana/fwd/eval.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/detail/wrong.hpp>
#include <boost/hana/functional/id.hpp>
namespace boost { namespace hana {
//! @cond
template <typename Expr>
constexpr decltype(auto) eval_t::operator()(Expr&& expr) const {
return eval_impl<typename hana::tag_of<Expr>::type>::apply(
static_cast<Expr&&>(expr)
);
}
//! @endcond
template <typename T, bool condition>
struct eval_impl<T, when<condition>> : default_ {
template <typename Expr>
static constexpr auto eval_helper(Expr&& expr, int)
-> decltype(static_cast<Expr&&>(expr)())
{ return static_cast<Expr&&>(expr)(); }
template <typename Expr>
static constexpr auto eval_helper(Expr&& expr, long)
-> decltype(static_cast<Expr&&>(expr)(hana::id))
{ return static_cast<Expr&&>(expr)(hana::id); }
template <typename Expr>
static constexpr auto eval_helper(Expr&&, ...) {
static_assert(detail::wrong<Expr>{},
"hana::eval(expr) requires the expression to be a hana::lazy, "
"a nullary Callable or a unary Callable that may be "
"called with hana::id");
}
template <typename Expr>
static constexpr decltype(auto) apply(Expr&& expr)
{ return eval_helper(static_cast<Expr&&>(expr), int{}); }
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EVAL_HPP

View File

@ -0,0 +1,93 @@
/*!
@file
Defines `boost::hana::eval_if`.
Copyright Louis Dionne 2013-2022
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_EVAL_IF_HPP
#define BOOST_HANA_EVAL_IF_HPP
#include <boost/hana/fwd/eval_if.hpp>
#include <boost/hana/bool.hpp>
#include <boost/hana/concept/constant.hpp>
#include <boost/hana/concept/logical.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/eval.hpp>
#include <boost/hana/if.hpp>
#include <type_traits>
namespace boost { namespace hana {
//! @cond
template <typename Cond, typename Then, typename Else>
constexpr decltype(auto) eval_if_t::operator()(Cond&& cond, Then&& then_, Else&& else_) const {
using Bool = typename hana::tag_of<Cond>::type;
using EvalIf = BOOST_HANA_DISPATCH_IF(eval_if_impl<Bool>,
hana::Logical<Bool>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Logical<Bool>::value,
"hana::eval_if(cond, then, else) requires 'cond' to be a Logical");
#endif
return EvalIf::apply(static_cast<Cond&&>(cond),
static_cast<Then&&>(then_),
static_cast<Else&&>(else_));
}
//! @endcond
template <typename L, bool condition>
struct eval_if_impl<L, when<condition>> : default_ {
template <typename ...Args>
static constexpr auto apply(Args&& ...) = delete;
};
//////////////////////////////////////////////////////////////////////////
// Model for arithmetic data types
//////////////////////////////////////////////////////////////////////////
template <typename L>
struct eval_if_impl<L, when<std::is_arithmetic<L>::value>> {
template <typename Cond, typename T, typename E>
static constexpr auto apply(Cond const& cond, T&& t, E&& e) {
return cond ? hana::eval(static_cast<T&&>(t))
: hana::eval(static_cast<E&&>(e));
}
};
//////////////////////////////////////////////////////////////////////////
// Model for Constants over a Logical
//////////////////////////////////////////////////////////////////////////
template <typename C>
struct eval_if_impl<C, when<
hana::Constant<C>::value &&
Logical<typename C::value_type>::value
>> {
template <typename Then, typename Else>
static constexpr decltype(auto)
eval_if_helper(hana::true_, Then&& t, Else&&)
{ return hana::eval(static_cast<Then&&>(t)); }
template <typename Then, typename Else>
static constexpr decltype(auto)
eval_if_helper(hana::false_, Then&&, Else&& e)
{ return hana::eval(static_cast<Else&&>(e)); }
template <typename Cond, typename Then, typename Else>
static constexpr decltype(auto) apply(Cond const&, Then&& t, Else&& e) {
constexpr auto cond = hana::value<Cond>();
constexpr bool truth_value = hana::if_(cond, true, false);
return eval_if_helper(hana::bool_<truth_value>{},
static_cast<Then&&>(t),
static_cast<Else&&>(e));
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EVAL_IF_HPP

View File

@ -0,0 +1,257 @@
/*
@file
Defines `boost::hana::experimental::print`.
Copyright Louis Dionne 2013-2022
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_EXPERIMENTAL_PRINTABLE_HPP
#define BOOST_HANA_EXPERIMENTAL_PRINTABLE_HPP
#include <boost/hana/concept/constant.hpp>
#include <boost/hana/concept/product.hpp>
#include <boost/hana/concept/sequence.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/to.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/first.hpp>
#include <boost/hana/for_each.hpp>
#include <boost/hana/intersperse.hpp>
#include <boost/hana/second.hpp>
#include <boost/hana/transform.hpp>
#include <boost/hana/tuple.hpp>
// models for different containers
#include <boost/hana/fwd/map.hpp>
#include <boost/hana/fwd/optional.hpp>
#include <boost/hana/fwd/set.hpp>
#include <boost/hana/fwd/string.hpp>
#include <boost/hana/fwd/type.hpp>
#include <boost/core/demangle.hpp>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
#include <typeinfo>
#include <utility>
namespace boost { namespace hana { namespace experimental {
template <typename T>
struct Printable;
//! @cond
template <typename T, typename = void>
struct print_impl : print_impl<T, hana::when<true>> { };
template <typename T, bool condition>
struct print_impl<T, hana::when<condition>> : hana::default_ {
template <typename ...Args>
static constexpr auto apply(Args&& ...) = delete;
};
//! @endcond
//! @ingroup group-experimental
//! Returns a string representation of the given object.
//!
//! This function is defined for most containers provided by Hana, and
//! also for objects that define an `operator<<` that can be used with
//! a `std::basic_ostream`. It can recursively print containers within
//! containers, but do not expect any kind of proper indentation.
//!
//! This function requires (the rest of) Boost to be available on the
//! system. It also requires RTTI to be enabled.
#ifdef BOOST_HANA_DOXYGEN_INVOKED
auto print = [](auto const& x) -> std::string {
return tag-dispatched;
};
#else
struct print_t {
template <typename T>
std::string operator()(T const& t) const {
using Tag = typename hana::tag_of<T>::type;
using Print = BOOST_HANA_DISPATCH_IF(print_impl<Tag>,
hana::experimental::Printable<Tag>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::experimental::Printable<Tag>::value,
"hana::experimental::print(t) requires 't' to be Printable");
#endif
return Print::apply(t);
}
};
BOOST_HANA_INLINE_VARIABLE constexpr print_t print{};
#endif
// Define the `Printable` concept
template <typename T>
struct Printable {
using Tag = typename hana::tag_of<T>::type;
static constexpr bool value = !hana::is_default<print_impl<Tag>>::value;
};
namespace print_detail {
inline std::string strip_type_junk(std::string const& str) {
return std::regex_replace(str, std::regex("(?:struct )?([a-z_]+::)*([a-z_]*)_t<((?:struct )?[a-z:<>_]*)>"), "$2<$3>");
}
}
// model for Sequences
template <typename S>
struct print_impl<S, hana::when<hana::Sequence<S>::value>> {
template <typename Xs>
static std::string apply(Xs const& xs) {
std::string result = "(";
auto comma_separated = hana::intersperse(xs, ", ");
hana::for_each(comma_separated, [&result](auto const& x) {
result += hana::experimental::print(x);
});
result += ")";
return result;
}
};
// model for OutputStreamable types
//! @cond
template <typename S>
struct print_impl<S, hana::when_valid<decltype(
std::declval<std::ostringstream&>() << std::declval<S const&>()
)>> {
template <typename T>
static std::string apply(T const& t) {
std::ostringstream os;
os << t;
return os.str();
}
};
//! @endcond
// model for hana::optional
template <>
struct print_impl<hana::optional_tag> {
template <typename O>
static std::string apply(O const& optional) {
return hana::maybe("nothing",
[](auto const& x) {
return "just(" + hana::experimental::print(x) + ")";
}, optional);
}
};
// model for hana::maps
template <>
struct print_impl<hana::map_tag> {
template <typename M>
static std::string apply(M const& map) {
std::string result = "{";
auto pairs = hana::transform(hana::to_tuple(map),
[](auto const& pair) {
return hana::experimental::print(hana::first(pair))
+ " => "
+ hana::experimental::print(hana::second(pair));
});
auto comma_separated = hana::intersperse(pairs, ", ");
hana::for_each(comma_separated, [&result](auto const& element) {
result += element;
});
result += "}";
return result;
}
};
// model for hana::metafunctions
template <template <typename ...> class F>
struct print_impl<hana::metafunction_t<F>> {
template <typename T>
static std::string apply(T const&) {
return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
}
};
// model for hana::metafunction_classes
template <typename F>
struct print_impl<hana::metafunction_class_t<F>> {
template <typename T>
static std::string apply(T const&) {
return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
}
};
// model for Constants holding a `Printable`
template <typename C>
struct print_impl<C, hana::when<
hana::Constant<C>::value &&
Printable<typename C::value_type>::value
>> {
template <typename T>
static std::string apply(T const&) {
constexpr auto value = hana::value<T>();
return hana::experimental::print(value);
}
};
// model for Products
template <typename P>
struct print_impl<P, hana::when<hana::Product<P>::value>> {
template <typename T>
static std::string apply(T const& t) {
return '(' + hana::experimental::print(hana::first(t))
+ ", "
+ hana::experimental::print(hana::second(t)) + ')';
}
};
// model for hana::strings
template <>
struct print_impl<hana::string_tag> {
template <typename S>
static std::string apply(S const& s) {
return '"' + std::string{hana::to<char const*>(s)} + '"';
}
};
// model for hana::sets
template <>
struct print_impl<hana::set_tag> {
template <typename S>
static std::string apply(S const& set) {
std::string result = "{";
auto as_tuple = hana::transform(hana::to_tuple(set),
hana::experimental::print);
auto comma_separated = hana::intersperse(as_tuple, ", ");
hana::for_each(comma_separated, [&result](auto const& element) {
result += element;
});
result += "}";
return result;
}
};
// model for hana::templates
template <template <typename ...> class F>
struct print_impl<template_t<F>> {
template <typename T>
static std::string apply(T const&) {
return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
}
};
// model for hana::types
template <>
struct print_impl<hana::type_tag> {
template <typename T>
static std::string apply(T const&) {
using Type = typename T::type;
return "type<" + boost::core::demangle(typeid(Type).name()) + '>';
}
};
} }} // end namespace boost::hana
#endif // !BOOST_HANA_EXPERIMENTAL_PRINTABLE_HPP

View File

@ -0,0 +1,64 @@
/*
@file
Defines `boost::hana::experimental::type_name`.
Copyright Louis Dionne 2013-2022
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_EXPERIMENTAL_TYPE_NAME_HPP
#define BOOST_HANA_EXPERIMENTAL_TYPE_NAME_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/string.hpp>
#include <cstddef>
#include <utility>
namespace boost { namespace hana { namespace experimental {
namespace detail {
struct cstring {
char const* ptr;
std::size_t length;
};
// Note: We substract the null terminator from the string sizes below.
template <typename T>
constexpr cstring type_name_impl2() {
#if defined(__clang__)
constexpr char const* pretty_function = __PRETTY_FUNCTION__;
constexpr std::size_t total_size = sizeof(__PRETTY_FUNCTION__) - 1;
constexpr std::size_t prefix_size = sizeof("boost::hana::experimental::detail::cstring boost::hana::experimental::detail::type_name_impl2() [T = ") - 1;
constexpr std::size_t suffix_size = sizeof("]") - 1;
#else
#error "No support for this compiler."
#endif
return {pretty_function + prefix_size, total_size - prefix_size - suffix_size};
}
template <typename T, std::size_t ...i>
auto type_name_impl1(std::index_sequence<i...>) {
constexpr auto name = detail::type_name_impl2<T>();
return hana::string<*(name.ptr + i)...>{};
}
} // end namespace detail
//! @ingroup group-experimental
//! Returns a `hana::string` representing the name of the given type, at
//! compile-time.
//!
//! This only works on Clang (and apparently MSVC, but Hana does not work
//! there as of writing this). Original idea taken from
//! https://github.com/Manu343726/ctti.
template <typename T>
auto type_name() {
constexpr auto name = detail::type_name_impl2<T>();
return detail::type_name_impl1<T>(std::make_index_sequence<name.length>{});
}
} }} // end namespace boost::hana
#endif // !BOOST_HANA_EXPERIMENTAL_TYPE_NAME_HPP

View File

@ -0,0 +1,158 @@
/*!
@file
Defines `boost::hana::experimental::types`.
Copyright Louis Dionne 2013-2022
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_EXPERIMENTAL_TYPES_HPP
#define BOOST_HANA_EXPERIMENTAL_TYPES_HPP
#include <boost/hana/bool.hpp>
#include <boost/hana/concept/metafunction.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/any_of.hpp>
#include <boost/hana/detail/type_at.hpp>
#include <boost/hana/fwd/at.hpp>
#include <boost/hana/fwd/contains.hpp>
#include <boost/hana/fwd/core/tag_of.hpp>
#include <boost/hana/fwd/equal.hpp>
#include <boost/hana/fwd/is_empty.hpp>
#include <boost/hana/fwd/transform.hpp>
#include <boost/hana/fwd/unpack.hpp>
#include <boost/hana/type.hpp>
#include <cstddef>
#include <type_traits>
#include <utility>
namespace boost { namespace hana {
namespace experimental {
//! @ingroup group-experimental
//! Container optimized for holding types.
//!
//! It is often useful to manipulate a sequence that contains types
//! only, without any associated runtime value. This container allows
//! storing and manipulating pure types in a much more compile-time
//! efficient manner than using `hana::tuple`, which must assume that
//! its contents might have runtime values.
template <typename ...T>
struct types;
struct types_tag;
template <typename ...T>
struct types { };
} // end namespace experimental
template <typename ...T>
struct tag_of<experimental::types<T...>> {
using type = experimental::types_tag;
};
// Foldable
template <>
struct unpack_impl<hana::experimental::types_tag> {
template <typename ...T, typename F, typename = typename std::enable_if<
!hana::Metafunction<F>::value
>::type>
static constexpr decltype(auto) apply(hana::experimental::types<T...> const&, F&& f) {
return static_cast<F&&>(f)(hana::type<T>{}...);
}
template <typename ...T, typename F, typename = typename std::enable_if<
hana::Metafunction<F>::value
>::type>
static constexpr hana::type<typename F::template apply<T...>::type>
apply(hana::experimental::types<T...> const&, F const&) { return {}; }
};
// Functor
template <>
struct transform_impl<hana::experimental::types_tag> {
template <typename ...T, typename F, typename = typename std::enable_if<
!hana::Metafunction<F>::value
>::type>
static constexpr auto apply(hana::experimental::types<T...> const&, F&& f)
-> hana::experimental::types<typename decltype(+f(hana::type<T>{}))::type...>
{ return {}; }
template <typename ...T, typename F, typename = typename std::enable_if<
hana::Metafunction<F>::value
>::type>
static constexpr hana::experimental::types<typename F::template apply<T>::type...>
apply(hana::experimental::types<T...> const&, F const&) { return {}; }
};
// Iterable
template <>
struct at_impl<hana::experimental::types_tag> {
template <typename ...T, typename N>
static constexpr auto
apply(hana::experimental::types<T...> const&, N const&) {
using Nth = typename detail::type_at<N::value, T...>::type;
return hana::type<Nth>{};
}
};
template <>
struct is_empty_impl<hana::experimental::types_tag> {
template <typename ...T>
static constexpr hana::bool_<sizeof...(T) == 0>
apply(hana::experimental::types<T...> const&)
{ return {}; }
};
template <>
struct drop_front_impl<hana::experimental::types_tag> {
template <std::size_t n, typename ...T, std::size_t ...i>
static hana::experimental::types<typename detail::type_at<i + n, T...>::type...>
helper(std::index_sequence<i...>);
template <typename ...T, typename N>
static constexpr auto
apply(hana::experimental::types<T...> const&, N const&) {
constexpr std::size_t n = N::value > sizeof...(T) ? sizeof...(T) : N::value;
using Indices = std::make_index_sequence<sizeof...(T) - n>;
return decltype(helper<n, T...>(Indices{})){};
}
};
// Searchable
template <>
struct contains_impl<hana::experimental::types_tag> {
template <typename U>
struct is_same_as {
template <typename T>
struct apply {
static constexpr bool value = std::is_same<U, T>::value;
};
};
template <typename ...T, typename U>
static constexpr auto apply(hana::experimental::types<T...> const&, U const&)
-> hana::bool_<
detail::any_of<is_same_as<typename U::type>::template apply, T...>::value
>
{ return {}; }
static constexpr hana::false_ apply(...) { return {}; }
};
// Comparable
template <>
struct equal_impl<hana::experimental::types_tag, hana::experimental::types_tag> {
template <typename Types>
static constexpr hana::true_ apply(Types const&, Types const&)
{ return {}; }
template <typename Ts, typename Us>
static constexpr hana::false_ apply(Ts const&, Us const&)
{ return {}; }
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXPERIMENTAL_TYPES_HPP

View File

@ -0,0 +1,515 @@
/*
@file
Defines experimental views.
Copyright Louis Dionne 2013-2022
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_EXPERIMENTAL_VIEW_HPP
#define BOOST_HANA_EXPERIMENTAL_VIEW_HPP
#include <boost/hana/and.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/bool.hpp>
#include <boost/hana/detail/decay.hpp>
#include <boost/hana/fold_left.hpp>
#include <boost/hana/functional/compose.hpp>
#include <boost/hana/functional/on.hpp>
#include <boost/hana/fwd/ap.hpp>
#include <boost/hana/fwd/concat.hpp>
#include <boost/hana/fwd/drop_front.hpp>
#include <boost/hana/fwd/empty.hpp>
#include <boost/hana/fwd/equal.hpp>
#include <boost/hana/fwd/flatten.hpp>
#include <boost/hana/fwd/is_empty.hpp>
#include <boost/hana/fwd/less.hpp>
#include <boost/hana/fwd/lift.hpp>
#include <boost/hana/fwd/transform.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/length.hpp>
#include <boost/hana/lexicographical_compare.hpp>
#include <boost/hana/range.hpp>
#include <boost/hana/tuple.hpp>
#include <boost/hana/unpack.hpp>
#include <cstddef>
#include <type_traits>
#include <utility>
// Pros of views
// - No temporary container created between algorithms
// - Lazy, so only the minimum is required
//
// Cons of views
// - Reference semantics mean possibility for dangling references
// - Lose the ability to move from temporary containers
// - When fetching the members of a view multiple times, no caching is done.
// So for example, `t = transform(xs, f); at_c<0>(t); at_c<0>(t)` will
// compute `f(at_c<0>(xs))` twice.
// - push_back creates a joint_view and a single_view. The single_view holds
// the value as a member. When doing multiple push_backs, we end up with a
// joint_view<xxx, joint_view<single_view<T>, joint_view<single_view<T>, ....>>>
// which contains a reference to `xxx` and all the `T`s by value. Such a
// "view" is not cheap to copy, which is inconsistent with the usual
// expectations about views.
namespace boost { namespace hana {
namespace experimental {
struct view_tag;
namespace detail {
template <typename Sequence>
struct is_view {
static constexpr bool value = false;
};
template <typename Sequence>
using view_storage = typename std::conditional<
detail::is_view<Sequence>::value, Sequence, Sequence&
>::type;
}
//////////////////////////////////////////////////////////////////////////
// sliced_view
//////////////////////////////////////////////////////////////////////////
template <typename Sequence, std::size_t ...indices>
struct sliced_view_t {
detail::view_storage<Sequence> sequence_;
using hana_tag = view_tag;
};
template <typename Sequence, typename Indices>
constexpr auto sliced(Sequence& sequence, Indices const& indices) {
return hana::unpack(indices, [&](auto ...i) {
return sliced_view_t<Sequence, decltype(i)::value...>{sequence};
});
}
namespace detail {
template <typename Sequence, std::size_t ...i>
struct is_view<sliced_view_t<Sequence, i...>> {
static constexpr bool value = true;
};
}
//////////////////////////////////////////////////////////////////////////
// transformed_view
//////////////////////////////////////////////////////////////////////////
template <typename Sequence, typename F>
struct transformed_view_t {
detail::view_storage<Sequence> sequence_;
F f_;
using hana_tag = view_tag;
};
template <typename Sequence, typename F>
constexpr transformed_view_t<Sequence, typename hana::detail::decay<F>::type>
transformed(Sequence& sequence, F&& f) {
return {sequence, static_cast<F&&>(f)};
}
namespace detail {
template <typename Sequence, typename F>
struct is_view<transformed_view_t<Sequence, F>> {
static constexpr bool value = true;
};
}
//////////////////////////////////////////////////////////////////////////
// filtered_view
//////////////////////////////////////////////////////////////////////////
#if 0
template <typename Sequence, typename Pred>
using filtered_view_t = sliced_view_t<Sequence, detail::filtered_indices<...>>;
template <typename Sequence, typename Pred>
constexpr filtered_view_t<Sequence, Pred> filtered(Sequence& sequence, Pred&& pred) {
return {sequence};
}
#endif
//////////////////////////////////////////////////////////////////////////
// joined_view
//////////////////////////////////////////////////////////////////////////
template <typename Sequence1, typename Sequence2>
struct joined_view_t {
detail::view_storage<Sequence1> sequence1_;
detail::view_storage<Sequence2> sequence2_;
using hana_tag = view_tag;
};
struct make_joined_view_t {
template <typename Sequence1, typename Sequence2>
constexpr joined_view_t<Sequence1, Sequence2> operator()(Sequence1& s1, Sequence2& s2) const {
return {s1, s2};
}
};
BOOST_HANA_INLINE_VARIABLE constexpr make_joined_view_t joined{};
namespace detail {
template <typename Sequence1, typename Sequence2>
struct is_view<joined_view_t<Sequence1, Sequence2>> {
static constexpr bool value = true;
};
}
//////////////////////////////////////////////////////////////////////////
// single_view
//////////////////////////////////////////////////////////////////////////
template <typename T>
struct single_view_t {
T value_;
using hana_tag = view_tag;
};
template <typename T>
constexpr single_view_t<typename hana::detail::decay<T>::type> single_view(T&& t) {
return {static_cast<T&&>(t)};
}
namespace detail {
template <typename T>
struct is_view<single_view_t<T>> {
static constexpr bool value = true;
};
}
//////////////////////////////////////////////////////////////////////////
// empty_view
//////////////////////////////////////////////////////////////////////////
struct empty_view_t {
using hana_tag = view_tag;
};
constexpr empty_view_t empty_view() {
return {};
}
namespace detail {
template <>
struct is_view<empty_view_t> {
static constexpr bool value = true;
};
}
} // end namespace experimental
//////////////////////////////////////////////////////////////////////////
// Foldable
//////////////////////////////////////////////////////////////////////////
template <>
struct unpack_impl<experimental::view_tag> {
// sliced_view
template <typename Sequence, std::size_t ...i, typename F>
static constexpr decltype(auto)
apply(experimental::sliced_view_t<Sequence, i...> view, F&& f) {
(void)view; // Remove spurious unused variable warning with GCC
return static_cast<F&&>(f)(hana::at_c<i>(view.sequence_)...);
}
// transformed_view
template <typename Sequence, typename F, typename G>
static constexpr decltype(auto)
apply(experimental::transformed_view_t<Sequence, F> view, G&& g) {
return hana::unpack(view.sequence_, hana::on(static_cast<G&&>(g), view.f_));
}
// joined_view
template <typename View, typename F, std::size_t ...i1, std::size_t ...i2>
static constexpr decltype(auto)
unpack_joined(View view, F&& f, std::index_sequence<i1...>,
std::index_sequence<i2...>)
{
(void)view; // Remove spurious unused variable warning with GCC
return static_cast<F&&>(f)(hana::at_c<i1>(view.sequence1_)...,
hana::at_c<i2>(view.sequence2_)...);
}
template <typename S1, typename S2, typename F>
static constexpr decltype(auto)
apply(experimental::joined_view_t<S1, S2> view, F&& f) {
constexpr auto N1 = decltype(hana::length(view.sequence1_))::value;
constexpr auto N2 = decltype(hana::length(view.sequence2_))::value;
return unpack_joined(view, static_cast<F&&>(f),
std::make_index_sequence<N1>{},
std::make_index_sequence<N2>{});
}
// single_view
template <typename T, typename F>
static constexpr decltype(auto) apply(experimental::single_view_t<T> view, F&& f) {
return static_cast<F&&>(f)(view.value_);
}
// empty_view
template <typename F>
static constexpr decltype(auto) apply(experimental::empty_view_t, F&& f) {
return static_cast<F&&>(f)();
}
};
//////////////////////////////////////////////////////////////////////////
// Iterable
//////////////////////////////////////////////////////////////////////////
template <>
struct at_impl<experimental::view_tag> {
// sliced_view
template <typename Sequence, std::size_t ...i, typename N>
static constexpr decltype(auto)
apply(experimental::sliced_view_t<Sequence, i...> view, N const&) {
constexpr std::size_t indices[] = {i...};
constexpr std::size_t n = indices[N::value];
return hana::at_c<n>(view.sequence_);
}
// transformed_view
template <typename Sequence, typename F, typename N>
static constexpr decltype(auto)
apply(experimental::transformed_view_t<Sequence, F> view, N const& n) {
return view.f_(hana::at(view.sequence_, n));
}
// joined_view
template <std::size_t Left, typename View, typename N>
static constexpr decltype(auto) at_joined_view(View view, N const&, hana::true_) {
return hana::at_c<N::value>(view.sequence1_);
}
template <std::size_t Left, typename View, typename N>
static constexpr decltype(auto) at_joined_view(View view, N const&, hana::false_) {
return hana::at_c<N::value - Left>(view.sequence2_);
}
template <typename S1, typename S2, typename N>
static constexpr decltype(auto)
apply(experimental::joined_view_t<S1, S2> view, N const& n) {
constexpr auto Left = decltype(hana::length(view.sequence1_))::value;
return at_joined_view<Left>(view, n, hana::bool_c<(N::value < Left)>);
}
// single_view
template <typename T, typename N>
static constexpr decltype(auto) apply(experimental::single_view_t<T> view, N const&) {
static_assert(N::value == 0,
"trying to fetch an out-of-bounds element in a hana::single_view");
return view.value_;
}
// empty_view
template <typename N>
static constexpr decltype(auto) apply(experimental::empty_view_t, N const&) = delete;
};
template <>
struct length_impl<experimental::view_tag> {
// sliced_view
template <typename Sequence, std::size_t ...i>
static constexpr auto
apply(experimental::sliced_view_t<Sequence, i...>) {
return hana::size_c<sizeof...(i)>;
}
// transformed_view
template <typename Sequence, typename F>
static constexpr auto apply(experimental::transformed_view_t<Sequence, F> view) {
return hana::length(view.sequence_);
}
// joined_view
template <typename S1, typename S2>
static constexpr auto apply(experimental::joined_view_t<S1, S2> view) {
return hana::size_c<
decltype(hana::length(view.sequence1_))::value +
decltype(hana::length(view.sequence2_))::value
>;
}
// single_view
template <typename T>
static constexpr auto apply(experimental::single_view_t<T>) {
return hana::size_c<1>;
}
// empty_view
static constexpr auto apply(experimental::empty_view_t) {
return hana::size_c<0>;
}
};
template <>
struct is_empty_impl<experimental::view_tag> {
// sliced_view
template <typename Sequence, std::size_t ...i>
static constexpr auto
apply(experimental::sliced_view_t<Sequence, i...>) {
return hana::bool_c<sizeof...(i) == 0>;
}
// transformed_view
template <typename Sequence, typename F>
static constexpr auto apply(experimental::transformed_view_t<Sequence, F> view) {
return hana::is_empty(view.sequence_);
}
// joined_view
template <typename S1, typename S2>
static constexpr auto apply(experimental::joined_view_t<S1, S2> view) {
return hana::and_(hana::is_empty(view.sequence1_),
hana::is_empty(view.sequence2_));
}
// single_view
template <typename T>
static constexpr auto apply(experimental::single_view_t<T>) {
return hana::false_c;
}
// empty_view
static constexpr auto apply(experimental::empty_view_t) {
return hana::true_c;
}
};
template <>
struct drop_front_impl<experimental::view_tag> {
template <typename View, typename N>
static constexpr auto apply(View view, N const&) {
constexpr auto n = N::value;
constexpr auto Length = decltype(hana::length(view))::value;
return experimental::sliced(view, hana::range_c<std::size_t, n, Length>);
}
};
//////////////////////////////////////////////////////////////////////////
// Functor
//////////////////////////////////////////////////////////////////////////
template <>
struct transform_impl<experimental::view_tag> {
template <typename Sequence, typename F, typename G>
static constexpr auto
apply(experimental::transformed_view_t<Sequence, F> view, G&& g) {
return experimental::transformed(view.sequence_,
hana::compose(static_cast<G&&>(g), view.f_));
}
template <typename View, typename F>
static constexpr auto apply(View view, F&& f) {
return experimental::transformed(view, static_cast<F&&>(f));
}
};
//////////////////////////////////////////////////////////////////////////
// Applicative
//////////////////////////////////////////////////////////////////////////
template <>
struct lift_impl<experimental::view_tag> {
template <typename T>
static constexpr auto apply(T&& t) {
return experimental::single_view(static_cast<T&&>(t));
}
};
template <>
struct ap_impl<experimental::view_tag> {
template <typename F, typename X>
static constexpr auto apply(F&& f, X&& x) {
// TODO: Implement cleverly; we most likely need a cartesian_product
// view or something like that.
return hana::ap(hana::to_tuple(f), hana::to_tuple(x));
}
};
//////////////////////////////////////////////////////////////////////////
// Monad
//////////////////////////////////////////////////////////////////////////
template <>
struct flatten_impl<experimental::view_tag> {
template <typename View>
static constexpr auto apply(View view) {
// TODO: Implement a flattened_view instead
return hana::fold_left(view, experimental::empty_view(),
experimental::joined);
}
};
//////////////////////////////////////////////////////////////////////////
// MonadPlus
//////////////////////////////////////////////////////////////////////////
template <>
struct concat_impl<experimental::view_tag> {
template <typename View1, typename View2>
static constexpr auto apply(View1 view1, View2 view2) {
return experimental::joined(view1, view2);
}
};
template <>
struct empty_impl<experimental::view_tag> {
static constexpr auto apply() {
return experimental::empty_view();
}
};
//////////////////////////////////////////////////////////////////////////
// Comparable
//////////////////////////////////////////////////////////////////////////
template <>
struct equal_impl<experimental::view_tag, experimental::view_tag> {
template <typename View1, typename View2>
static constexpr auto apply(View1 v1, View2 v2) {
// TODO: Use a lexicographical comparison algorithm.
return hana::equal(hana::to_tuple(v1), hana::to_tuple(v2));
}
};
template <typename S>
struct equal_impl<experimental::view_tag, S, hana::when<hana::Sequence<S>::value>> {
template <typename View1, typename Seq>
static constexpr auto apply(View1 v1, Seq const& s) {
// TODO: Use a lexicographical comparison algorithm.
return hana::equal(hana::to_tuple(v1), hana::to_tuple(s));
}
};
template <typename S>
struct equal_impl<S, experimental::view_tag, hana::when<hana::Sequence<S>::value>> {
template <typename Seq, typename View2>
static constexpr auto apply(Seq const& s, View2 v2) {
// TODO: Use a lexicographical comparison algorithm.
return hana::equal(hana::to_tuple(s), hana::to_tuple(v2));
}
};
//////////////////////////////////////////////////////////////////////////
// Orderable
//////////////////////////////////////////////////////////////////////////
template <>
struct less_impl<experimental::view_tag, experimental::view_tag> {
template <typename View1, typename View2>
static constexpr auto apply(View1 v1, View2 v2) {
return hana::lexicographical_compare(v1, v2);
}
};
template <typename S>
struct less_impl<experimental::view_tag, S, hana::when<hana::Sequence<S>::value>> {
template <typename View1, typename Seq>
static constexpr auto apply(View1 v1, Seq const& s) {
return hana::lexicographical_compare(v1, s);
}
};
template <typename S>
struct less_impl<S, experimental::view_tag, hana::when<hana::Sequence<S>::value>> {
template <typename Seq, typename View2>
static constexpr auto apply(Seq const& s, View2 v2) {
return hana::lexicographical_compare(s, v2);
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXPERIMENTAL_VIEW_HPP

View File

@ -0,0 +1,21 @@
/*!
@file
Includes all the adaptors for external Boost libraries.
Copyright Louis Dionne 2013-2022
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_EXT_BOOST_HPP
#define BOOST_HANA_EXT_BOOST_HPP
//! @ingroup group-ext
//! @defgroup group-ext-boost Other Boost adapters
//! Adapters for miscellaneous heterogeneous containers in Boost.
#include <boost/hana/ext/boost/fusion.hpp>
#include <boost/hana/ext/boost/mpl.hpp>
#include <boost/hana/ext/boost/tuple.hpp>
#endif // !BOOST_HANA_EXT_BOOST_HPP

View File

@ -0,0 +1,22 @@
/*!
@file
Includes all the adaptors for the Boost.Fusion library.
Copyright Louis Dionne 2013-2022
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_EXT_BOOST_FUSION_HPP
#define BOOST_HANA_EXT_BOOST_FUSION_HPP
//! @ingroup group-ext
//! @defgroup group-ext-fusion Boost.Fusion adapters
//! Adapters for Boost.Fusion containers.
#include <boost/hana/ext/boost/fusion/deque.hpp>
#include <boost/hana/ext/boost/fusion/list.hpp>
#include <boost/hana/ext/boost/fusion/tuple.hpp>
#include <boost/hana/ext/boost/fusion/vector.hpp>
#endif // !BOOST_HANA_EXT_BOOST_FUSION_HPP

View File

@ -0,0 +1,108 @@
/*!
@file
Adapts `boost::fusion::deque` for use with Hana.
Copyright Louis Dionne 2013-2022
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_EXT_BOOST_FUSION_DEQUE_HPP
#define BOOST_HANA_EXT_BOOST_FUSION_DEQUE_HPP
#include <boost/hana/at.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/ext/boost/fusion/detail/common.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/length.hpp>
#include <boost/fusion/container/deque.hpp>
#include <boost/fusion/container/generation/make_deque.hpp>
#include <boost/fusion/support/tag_of.hpp>
#include <cstddef>
#include <type_traits>
#include <utility>
#ifdef BOOST_HANA_DOXYGEN_INVOKED
namespace boost { namespace fusion {
//! @ingroup group-ext-fusion
//! Adapter for Boost.Fusion deques.
//!
//!
//! Modeled concepts
//! ----------------
//! A Fusion deque is a model of the `Sequence` concept, and all the
//! concepts it refines. That makes it essentially the same as a Hana
//! tuple, although the complexity of some operations might differ from
//! that of a tuple.
//!
//! @include example/ext/boost/fusion/deque.cpp
template <typename ...T>
struct deque { };
}}
#endif
namespace boost { namespace hana {
namespace ext { namespace boost { namespace fusion {
struct deque_tag;
}}}
template <typename T>
struct tag_of<T, when<
std::is_same<
typename ::boost::fusion::traits::tag_of<T>::type,
::boost::fusion::traits::tag_of<
::boost::fusion::deque<>
>::type
>::value
>> {
using type = ext::boost::fusion::deque_tag;
};
namespace detail {
template <>
struct is_fusion_sequence<ext::boost::fusion::deque_tag> {
static constexpr bool value = true;
};
}
//////////////////////////////////////////////////////////////////////////
// Iterable (the rest is in detail/common.hpp)
//////////////////////////////////////////////////////////////////////////
template <>
struct drop_front_impl<ext::boost::fusion::deque_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<ext::boost::fusion::deque_tag>(
hana::at_c<n + i>(static_cast<Xs&&>(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;
return drop_front_helper<n>(static_cast<Xs&&>(xs),
std::make_index_sequence<(n < len ? len - n : 0)>{});
}
};
//////////////////////////////////////////////////////////////////////////
// Sequence
//////////////////////////////////////////////////////////////////////////
template <>
struct make_impl<ext::boost::fusion::deque_tag> {
template <typename ...Xs>
static constexpr auto apply(Xs&& ...xs) {
return ::boost::fusion::make_deque(static_cast<Xs&&>(xs)...);
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_BOOST_FUSION_DEQUE_HPP

View File

@ -0,0 +1,79 @@
/*!
@file
Defines common methods for all Boost.Fusion sequences.
Copyright Louis Dionne 2013-2022
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_EXT_BOOST_FUSION_DETAIL_COMMON_HPP
#define BOOST_HANA_EXT_BOOST_FUSION_DETAIL_COMMON_HPP
#include <boost/hana/bool.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/fwd/at.hpp>
#include <boost/hana/fwd/concept/sequence.hpp>
#include <boost/hana/fwd/is_empty.hpp>
#include <boost/hana/fwd/length.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/fusion/sequence/intrinsic/at.hpp>
#include <boost/fusion/sequence/intrinsic/empty.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <cstddef>
namespace boost { namespace hana {
namespace detail {
template <typename T>
struct is_fusion_sequence {
static constexpr bool value = false;
};
}
//////////////////////////////////////////////////////////////////////////
// Iterable
//////////////////////////////////////////////////////////////////////////
template <typename S>
struct at_impl<S, when<detail::is_fusion_sequence<S>::value>> {
template <typename Xs, typename N>
static constexpr decltype(auto) apply(Xs&& xs, N const&) {
constexpr std::size_t n = N::value;
return boost::fusion::at_c<n>(static_cast<Xs&&>(xs));
}
};
template <typename S>
struct is_empty_impl<S, when<detail::is_fusion_sequence<S>::value>> {
template <typename Xs>
static constexpr auto apply(Xs&& xs) {
using Empty = decltype(boost::fusion::empty(xs));
return hana::bool_c<Empty::value>;
}
};
//////////////////////////////////////////////////////////////////////////
// Foldable
//////////////////////////////////////////////////////////////////////////
template <typename S>
struct length_impl<S, when<detail::is_fusion_sequence<S>::value>> {
template <typename Xs>
static constexpr auto apply(Xs const&) {
using Size = typename boost::fusion::result_of::size<Xs>::type;
return hana::size_c<Size::value>;
}
};
//////////////////////////////////////////////////////////////////////////
// Sequence
//////////////////////////////////////////////////////////////////////////
template <typename S>
struct Sequence<S, when<detail::is_fusion_sequence<S>::value>> {
static constexpr bool value = true;
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_BOOST_FUSION_DETAIL_COMMON_HPP

View File

@ -0,0 +1,111 @@
/*!
@file
Adapts `boost::fusion::list` for use with Hana.
Copyright Louis Dionne 2013-2022
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_EXT_BOOST_FUSION_LIST_HPP
#define BOOST_HANA_EXT_BOOST_FUSION_LIST_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/ext/boost/fusion/detail/common.hpp>
#include <boost/hana/fwd/at.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/length.hpp>
#include <boost/fusion/algorithm/transformation/pop_front.hpp>
#include <boost/fusion/container/generation/make_list.hpp>
#include <boost/fusion/container/list.hpp>
#include <boost/fusion/container/list/convert.hpp>
#include <boost/fusion/support/tag_of.hpp>
#include <boost/version.hpp>
#include <cstddef>
#include <type_traits>
#include <utility>
#ifdef BOOST_HANA_DOXYGEN_INVOKED
namespace boost { namespace fusion {
//! @ingroup group-ext-fusion
//! Adapter for Boost.Fusion lists.
//!
//!
//! Modeled concepts
//! ----------------
//! A Fusion list is a model of the `Sequence` concept, and all the
//! concepts it refines. That makes it essentially the same as a Hana
//! tuple, although the complexity of some operations might differ from
//! that of a tuple.
//!
//! @include example/ext/boost/fusion/list.cpp
template <typename ...T>
struct list { };
}}
#endif
namespace boost { namespace hana {
namespace ext { namespace boost { namespace fusion {
struct list_tag;
}}}
template <typename T>
struct tag_of<T, when<
std::is_same<
typename ::boost::fusion::traits::tag_of<T>::type,
::boost::fusion::traits::tag_of<
::boost::fusion::list<>
>::type
>::value
>> {
using type = ext::boost::fusion::list_tag;
};
namespace detail {
template <>
struct is_fusion_sequence<ext::boost::fusion::list_tag> {
static constexpr bool value = true;
};
}
//////////////////////////////////////////////////////////////////////////
// Iterable (the rest is in detail/common.hpp)
//////////////////////////////////////////////////////////////////////////
template <>
struct drop_front_impl<ext::boost::fusion::list_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<ext::boost::fusion::list_tag>(
hana::at_c<n + i>(static_cast<Xs&&>(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;
return drop_front_helper<n>(static_cast<Xs&&>(xs),
std::make_index_sequence<(n < len ? len - n : 0)>{});
}
};
//////////////////////////////////////////////////////////////////////////
// Sequence
//////////////////////////////////////////////////////////////////////////
template <>
struct make_impl<ext::boost::fusion::list_tag> {
template <typename ...Xs>
static constexpr auto apply(Xs&& ...xs) {
return ::boost::fusion::make_list(static_cast<Xs&&>(xs)...);
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_BOOST_FUSION_LIST_HPP

View File

@ -0,0 +1,49 @@
/*!
@file
Adapts `boost::fusion::tuple` for use with Hana.
In the current version of Boost.Fusion, `boost::fusion::tuple` is basically
an alias to `boost::fusion::vector`, so both data types share the same
implementation in Hana.
Copyright Louis Dionne 2013-2022
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_EXT_BOOST_FUSION_TUPLE_HPP
#define BOOST_HANA_EXT_BOOST_FUSION_TUPLE_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/ext/boost/fusion/vector.hpp>
#ifdef BOOST_HANA_DOXYGEN_INVOKED
namespace boost { namespace fusion {
//! @ingroup group-ext-fusion
//! Adapter for Boost.Fusion tuples.
//!
//!
//! Modeled concepts
//! ----------------
//! A Fusion tuple is a model of the `Sequence` concept, and all the
//! concepts it refines. That makes it essentially the same as a Hana
//! tuple, although the complexity of some operations might differ from
//! that of a tuple.
//!
//! @include example/ext/boost/fusion/tuple.cpp
template <typename ...T>
struct tuple { };
}}
#endif
namespace boost { namespace hana {
namespace ext { namespace boost { namespace fusion {
// In the current version of Boost.Fusion, `boost::fusion::tuple` is
// basically an alias to `boost::fusion::vector`, hence the alias.
using tuple_tag = vector_tag;
}}}
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_BOOST_FUSION_TUPLE_HPP

View File

@ -0,0 +1,110 @@
/*!
@file
Adapts `boost::fusion::vector` for use with Hana.
Copyright Louis Dionne 2013-2022
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_EXT_BOOST_FUSION_VECTOR_HPP
#define BOOST_HANA_EXT_BOOST_FUSION_VECTOR_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/ext/boost/fusion/detail/common.hpp>
#include <boost/hana/fwd/at.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/length.hpp>
#include <boost/fusion/algorithm/transformation/pop_front.hpp>
#include <boost/fusion/container/generation/make_vector.hpp>
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/container/vector/convert.hpp>
#include <boost/fusion/support/tag_of.hpp>
#include <cstddef>
#include <type_traits>
#include <utility>
#ifdef BOOST_HANA_DOXYGEN_INVOKED
namespace boost { namespace fusion {
//! @ingroup group-ext-fusion
//! Adapter for Boost.Fusion vectors.
//!
//!
//! Modeled concepts
//! ----------------
//! A Fusion vector is a model of the `Sequence` concept, and all the
//! concepts it refines. That makes it essentially the same as a Hana
//! tuple, although the complexity of some operations might differ from
//! that of a tuple.
//!
//! @include example/ext/boost/fusion/vector.cpp
template <typename ...T>
struct vector { };
}}
#endif
namespace boost { namespace hana {
namespace ext { namespace boost { namespace fusion {
struct vector_tag;
}}}
template <typename T>
struct tag_of<T, when<
std::is_same<
typename ::boost::fusion::traits::tag_of<T>::type,
::boost::fusion::traits::tag_of<
::boost::fusion::vector<>
>::type
>::value
>> {
using type = ext::boost::fusion::vector_tag;
};
namespace detail {
template <>
struct is_fusion_sequence<ext::boost::fusion::vector_tag> {
static constexpr bool value = true;
};
}
//////////////////////////////////////////////////////////////////////////
// Iterable (the rest is in detail/common.hpp)
//////////////////////////////////////////////////////////////////////////
template <>
struct drop_front_impl<ext::boost::fusion::vector_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<ext::boost::fusion::vector_tag>(
hana::at_c<n + i>(static_cast<Xs&&>(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;
return drop_front_helper<n>(static_cast<Xs&&>(xs),
std::make_index_sequence<(n < len ? len - n : 0)>{});
}
};
//////////////////////////////////////////////////////////////////////////
// Sequence
//////////////////////////////////////////////////////////////////////////
template <>
struct make_impl<ext::boost::fusion::vector_tag> {
template <typename ...Xs>
static constexpr auto apply(Xs&& ...xs) {
return ::boost::fusion::make_vector(static_cast<Xs&&>(xs)...);
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_BOOST_FUSION_VECTOR_HPP

View File

@ -0,0 +1,21 @@
/*!
@file
Includes all the adaptors for the Boost.MPL library.
Copyright Louis Dionne 2013-2022
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_EXT_BOOST_MPL_HPP
#define BOOST_HANA_EXT_BOOST_MPL_HPP
//! @ingroup group-ext
//! @defgroup group-ext-mpl Boost.MPL adapters
//! Adapters for Boost.MPL containers.
#include <boost/hana/ext/boost/mpl/integral_c.hpp>
#include <boost/hana/ext/boost/mpl/list.hpp>
#include <boost/hana/ext/boost/mpl/vector.hpp>
#endif // !BOOST_HANA_EXT_BOOST_MPL_HPP

View File

@ -0,0 +1,81 @@
/*!
@file
Adapts Boost.MPL IntegralConstants for use with Hana.
Copyright Louis Dionne 2013-2022
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_EXT_BOOST_MPL_INTEGRAL_C_HPP
#define BOOST_HANA_EXT_BOOST_MPL_INTEGRAL_C_HPP
#include <boost/hana/concept/integral_constant.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/fwd/core/to.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/integral_c_tag.hpp>
#include <type_traits>
#ifdef BOOST_HANA_DOXYGEN_INVOKED
namespace boost { namespace mpl {
//! @ingroup group-ext-mpl
//! Adapter for IntegralConstants from the Boost.MPL.
//!
//! Provided models
//! ---------------
//! 1. `Constant` and `IntegralConstant`\n
//! A Boost.MPL IntegralConstant is a model of the `IntegralConstant`
//! and `Constant` concepts just like `hana::integral_constant`s are.
//! As a consequence, they are also implicitly a model of the concepts
//! provided for all models of `Constant`.
//! @include example/ext/boost/mpl/integral_c/integral_constant.cpp
template <typename T, T v>
struct integral_c { };
}}
#endif
namespace boost { namespace hana {
namespace ext { namespace boost { namespace mpl {
template <typename T>
struct integral_c_tag { using value_type = T; };
}}}
template <typename T>
struct tag_of<T, when<
std::is_same<
typename T::tag,
::boost::mpl::integral_c_tag
>::value
>> {
using type = ext::boost::mpl::integral_c_tag<
typename hana::tag_of<typename T::value_type>::type
>;
};
//////////////////////////////////////////////////////////////////////////
// IntegralConstant/Constant
//////////////////////////////////////////////////////////////////////////
template <typename T>
struct IntegralConstant<ext::boost::mpl::integral_c_tag<T>> {
static constexpr bool value = true;
};
template <typename T, typename C>
struct to_impl<ext::boost::mpl::integral_c_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 ::boost::mpl::integral_c<T, N::value>{};
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_BOOST_MPL_INTEGRAL_C_HPP

View File

@ -0,0 +1,186 @@
/*!
@file
Adapts `boost::mpl::list` for use with Hana.
Copyright Louis Dionne 2013-2022
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_EXT_BOOST_MPL_LIST_HPP
#define BOOST_HANA_EXT_BOOST_MPL_LIST_HPP
#include <boost/hana/concept/foldable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/ext/boost/mpl/integral_c.hpp>
#include <boost/hana/fwd/at.hpp>
#include <boost/hana/fwd/core/to.hpp>
#include <boost/hana/fwd/core/tag_of.hpp>
#include <boost/hana/fwd/drop_front.hpp>
#include <boost/hana/fwd/equal.hpp>
#include <boost/hana/fwd/is_empty.hpp>
#include <boost/hana/fwd/less.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/length.hpp>
#include <boost/hana/type.hpp>
#include <boost/hana/unpack.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/empty.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/list.hpp>
#include <boost/mpl/sequence_tag.hpp>
#include <boost/mpl/size.hpp>
#include <cstddef>
#include <type_traits>
#include <utility>
#ifdef BOOST_HANA_DOXYGEN_INVOKED
namespace boost { namespace mpl {
//! @ingroup group-ext-mpl
//! Adapter for Boost.MPL lists.
//!
//!
//! Modeled concepts
//! ----------------
//! It is possible for MPL lists to model a couple of concepts.
//! However, because they are only able to hold types, they lack
//! the generality required to model concepts like `Functor`,
//! `Sequence` and other related concepts.
//!
//! 1. `Comparable`\n
//! Two MPL lists are equal if and only if they contain the same
//! number of types, and if all those types are equal.
//! @include example/ext/boost/mpl/list/comparable.cpp
//!
//! 2. `Foldable`\n
//! Folding a MPL list is equivalent to folding it as a `Sequence`.
//! @include example/ext/boost/mpl/list/foldable.cpp
//!
//! 3. `Iterable`\n
//! Iterating over a MPL list is just iterating over each of the
//! types it contains, as if it were a `Sequence`.
//! @include example/ext/boost/mpl/list/iterable.cpp
//!
//! 4. `Searchable`\n
//! A MPL list can be searched as if it were a tuple containing
//! `hana::type`s.
//! @include example/ext/boost/mpl/list/searchable.cpp
//!
//!
//! Conversion from any `Foldable`
//! ------------------------------
//! A MPL list can be created from any `Foldable`. More precisely,
//! for a `Foldable` `xs` whose linearization is `[x1, ..., xn]`,
//! @code
//! to<ext::boost::mpl::list_tag>(xs) == mpl::list<t1, ..., tn>{}
//! @endcode
//! where `tk` is the type of `xk`, or the type contained in `xk` if
//! `xk` is a `hana::type`.
//! @warning
//! The limitations on the size of `mpl::list`s are inherited by
//! this conversion utility, and hence trying to convert a `Foldable`
//! containing more than [BOOST_MPL_LIMIT_LIST_SIZE][1] elements is
//! an error.
//! @include example/ext/boost/mpl/list/conversion.cpp
//!
//! [1]: http://www.boost.org/doc/libs/release/libs/mpl/doc/refmanual/limit-list-size.html
template <typename ...T>
struct list { };
}}
#endif
namespace boost { namespace hana {
namespace ext { namespace boost { namespace mpl {
using list_tag = ::boost::mpl::sequence_tag< ::boost::mpl::list<>>::type;
}}}
template <typename T>
struct tag_of<T, when<
std::is_same<
typename ::boost::mpl::sequence_tag<T>::type,
::boost::mpl::sequence_tag< ::boost::mpl::list<>>::type
>::value
>> {
using type = ext::boost::mpl::list_tag;
};
//////////////////////////////////////////////////////////////////////////
// Comparable
//////////////////////////////////////////////////////////////////////////
template <>
struct equal_impl<ext::boost::mpl::list_tag, ext::boost::mpl::list_tag> {
template <typename Xs, typename Ys>
static constexpr auto apply(Xs const&, Ys const&) {
return typename ::boost::mpl::equal<Xs, Ys>::type{};
}
};
//////////////////////////////////////////////////////////////////////////
// Foldable
//////////////////////////////////////////////////////////////////////////
template <>
struct length_impl<ext::boost::mpl::list_tag> {
template <typename Xs>
static constexpr auto apply(Xs const&) {
return hana::size_c< ::boost::mpl::size<Xs>::type::value>;
}
};
//////////////////////////////////////////////////////////////////////////
// Iterable
//////////////////////////////////////////////////////////////////////////
template <>
struct at_impl<ext::boost::mpl::list_tag> {
template <typename Ts, typename N>
static constexpr auto apply(Ts const&, N const&) {
constexpr std::size_t n = N::value;
using T = typename ::boost::mpl::at_c<Ts, n>::type;
return hana::type_c<T>;
}
};
template <>
struct drop_front_impl<ext::boost::mpl::list_tag> {
template <std::size_t n, typename Xs, std::size_t ...i>
static constexpr auto drop_front_helper(Xs const&, std::index_sequence<i...>) {
return boost::mpl::list<
typename boost::mpl::at_c<Xs, n + i>::type...
>{};
}
template <typename Xs, typename N>
static constexpr auto apply(Xs const& xs, N const&) {
constexpr std::size_t n = N::value;
constexpr std::size_t len = decltype(hana::length(xs))::value;
return drop_front_helper<n>(xs,
std::make_index_sequence<(n < len ? len - n : 0)>{});
}
};
template <>
struct is_empty_impl<ext::boost::mpl::list_tag> {
template <typename Xs>
static constexpr auto apply(Xs const&)
{ return typename ::boost::mpl::empty<Xs>::type{}; }
};
//////////////////////////////////////////////////////////////////////////
// Conversion from a Foldable
//////////////////////////////////////////////////////////////////////////
template <typename F>
struct to_impl<ext::boost::mpl::list_tag, F, when<hana::Foldable<F>::value>> {
template <typename Xs>
static constexpr decltype(auto) apply(Xs&& xs) {
auto list_type = hana::unpack(static_cast<Xs&&>(xs),
hana::template_<::boost::mpl::list>);
return typename decltype(list_type)::type{};
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_BOOST_MPL_LIST_HPP

View File

@ -0,0 +1,201 @@
/*!
@file
Adapts `boost::mpl::vector` for use with Hana.
Copyright Louis Dionne 2013-2022
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_EXT_BOOST_MPL_VECTOR_HPP
#define BOOST_HANA_EXT_BOOST_MPL_VECTOR_HPP
#include <boost/hana/concept/foldable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/ext/boost/mpl/integral_c.hpp>
#include <boost/hana/fwd/at.hpp>
#include <boost/hana/fwd/core/to.hpp>
#include <boost/hana/fwd/core/tag_of.hpp>
#include <boost/hana/fwd/drop_front.hpp>
#include <boost/hana/fwd/equal.hpp>
#include <boost/hana/fwd/is_empty.hpp>
#include <boost/hana/fwd/less.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/length.hpp>
#include <boost/hana/type.hpp>
#include <boost/hana/unpack.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/empty.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/sequence_tag.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/vector.hpp>
#include <cstddef>
#include <type_traits>
#include <utility>
#ifdef BOOST_HANA_DOXYGEN_INVOKED
namespace boost { namespace mpl {
//! @ingroup group-ext-mpl
//! Adapter for Boost.MPL vectors.
//!
//!
//! Modeled concepts
//! ----------------
//! It is possible for MPL vectors to model a couple of concepts.
//! However, because they are only able to hold types, they lack
//! the generality required to model concepts like `Functor`,
//! `Sequence` and other related concepts.
//!
//! 1. `Comparable`\n
//! Two MPL vectors are equal if and only if they contain the same
//! number of types, and if all those types are equal.
//! @include example/ext/boost/mpl/vector/comparable.cpp
//!
//! 2. `Foldable`\n
//! Folding a MPL vector is equivalent to folding it as a `Sequence`.
//! @include example/ext/boost/mpl/vector/foldable.cpp
//!
//! 3. `Iterable`\n
//! Iterating over a MPL vector is just iterating over each of the
//! types it contains, as if it were a `Sequence`.
//! @include example/ext/boost/mpl/vector/iterable.cpp
//!
//! 4. `Searchable`\n
//! A MPL vector can be searched as if it were a tuple containing
//! `hana::type`s.
//! @include example/ext/boost/mpl/vector/searchable.cpp
//!
//!
//! Conversion from any `Foldable`
//! ------------------------------
//! A MPL vector can be created from any `Foldable`. More precisely,
//! for a `Foldable` `xs` whose linearization is `[x1, ..., xn]`,
//! @code
//! to<ext::boost::mpl::vector_tag>(xs) == mpl::vector<t1, ..., tn>
//! @endcode
//! where `tk` is the type of `xk`, or the type contained in `xk` if
//! `xk` is a `hana::type`.
//! @warning
//! The limitations on the size of `mpl::vector`s are inherited by
//! this conversion utility, and hence trying to convert a `Foldable`
//! containing more than [BOOST_MPL_LIMIT_VECTOR_SIZE][1] elements
//! is an error.
//! @include example/ext/boost/mpl/vector/conversion.cpp
//!
//! [1]: http://www.boost.org/doc/libs/release/libs/mpl/doc/refmanual/limit-vector-size.html
template <typename ...T>
struct vector { };
}}
#endif
namespace boost { namespace hana {
namespace ext { namespace boost { namespace mpl {
using vector_tag = ::boost::mpl::sequence_tag< ::boost::mpl::vector<>>::type;
}}}
namespace mpl_detail {
// When `BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES` is not defined (e.g. on
// MSVC), different MPL sequences (like vector0 and vector1) have different
// tags, so we need to take that into account when we compare them.
#ifndef BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES
template <typename T1, typename T2>
struct is_same_mpl_vector_tag : std::false_type { };
template <template <long> class Tag, long x, long y>
struct is_same_mpl_vector_tag<Tag<x>, Tag<y>> : std::true_type { };
#else
template <typename T1, typename T2>
struct is_same_mpl_vector_tag : std::is_same<T1, T2> { };
#endif
}
template <typename T>
struct tag_of<T, when<
mpl_detail::is_same_mpl_vector_tag<
typename ::boost::mpl::sequence_tag<T>::type,
::boost::mpl::sequence_tag< ::boost::mpl::vector<>>::type
>::value
>> {
using type = ext::boost::mpl::vector_tag;
};
//////////////////////////////////////////////////////////////////////////
// Comparable
//////////////////////////////////////////////////////////////////////////
template <>
struct equal_impl<ext::boost::mpl::vector_tag, ext::boost::mpl::vector_tag> {
template <typename Xs, typename Ys>
static constexpr auto apply(Xs const&, Ys const&) {
return typename ::boost::mpl::equal<Xs, Ys>::type{};
}
};
//////////////////////////////////////////////////////////////////////////
// Foldable
//////////////////////////////////////////////////////////////////////////
template <>
struct length_impl<ext::boost::mpl::vector_tag> {
template <typename Xs>
static constexpr auto apply(Xs const&) {
return hana::size_c< ::boost::mpl::size<Xs>::type::value>;
}
};
//////////////////////////////////////////////////////////////////////////
// Iterable
//////////////////////////////////////////////////////////////////////////
template <>
struct at_impl<ext::boost::mpl::vector_tag> {
template <typename Ts, typename N>
static constexpr auto apply(Ts const&, N const&) {
constexpr std::size_t n = N::value;
using T = typename ::boost::mpl::at_c<Ts, n>::type;
return hana::type_c<T>;
}
};
template <>
struct drop_front_impl<ext::boost::mpl::vector_tag> {
template <std::size_t n, typename Xs, std::size_t ...i>
static constexpr auto drop_front_helper(Xs const&, std::index_sequence<i...>) {
return boost::mpl::vector<
typename boost::mpl::at_c<Xs, n + i>::type...
>{};
}
template <typename Xs, typename N>
static constexpr auto apply(Xs const& xs, N const&) {
constexpr std::size_t n = N::value;
constexpr std::size_t len = decltype(hana::length(xs))::value;
return drop_front_helper<n>(xs,
std::make_index_sequence<(n < len ? len - n : 0)>{});
}
};
template <>
struct is_empty_impl<ext::boost::mpl::vector_tag> {
template <typename xs>
static constexpr auto apply(xs)
{ return typename ::boost::mpl::empty<xs>::type{}; }
};
//////////////////////////////////////////////////////////////////////////
// Conversion from a Foldable
//////////////////////////////////////////////////////////////////////////
template <typename F>
struct to_impl<ext::boost::mpl::vector_tag, F, when<hana::Foldable<F>::value>> {
template <typename Xs>
static constexpr auto apply(Xs const& xs) {
auto vector_type = hana::unpack(xs, hana::template_<boost::mpl::vector>);
return typename decltype(vector_type)::type{};
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_BOOST_MPL_VECTOR_HPP

View File

@ -0,0 +1,138 @@
/*!
@file
Adapts `boost::tuple` for use with Hana.
Copyright Louis Dionne 2013-2022
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_EXT_BOOST_TUPLE_HPP
#define BOOST_HANA_EXT_BOOST_TUPLE_HPP
#include <boost/hana/bool.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <boost/hana/fwd/at.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/length.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/tuple/tuple.hpp>
#include <cstddef>
#include <utility>
#ifdef BOOST_HANA_DOXYGEN_INVOKED
namespace boost {
//! @ingroup group-ext-boost
//! Adapter for `boost::tuple`s.
//!
//!
//! Modeled concepts
//! ----------------
//! A `boost::tuple` is a model of the `Sequence` concept, and all the
//! concepts it refines. That makes it essentially the same as a Hana
//! tuple, although the complexity of some operations might differ from
//! that of Hana's tuple.
//!
//! @include example/ext/boost/tuple.cpp
template <typename ...T>
struct tuple { };
}
#endif
namespace boost { namespace hana {
namespace ext { namespace boost { struct tuple_tag; }}
template <typename ...Xs>
struct tag_of<boost::tuple<Xs...>> {
using type = ext::boost::tuple_tag;
};
template <typename H, typename T>
struct tag_of<boost::tuples::cons<H, T>> {
using type = ext::boost::tuple_tag;
};
template <>
struct tag_of<boost::tuples::null_type> {
using type = ext::boost::tuple_tag;
};
//////////////////////////////////////////////////////////////////////////
// Iterable
//////////////////////////////////////////////////////////////////////////
template <>
struct at_impl<ext::boost::tuple_tag> {
template <typename Xs, typename N>
static constexpr decltype(auto) apply(Xs&& xs, N const&) {
constexpr std::size_t n = N::value;
return static_cast<Xs&&>(xs).template get<n>();
}
};
template <>
struct drop_front_impl<ext::boost::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<ext::boost::tuple_tag>(
hana::at_c<n + i>(static_cast<Xs&&>(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;
return drop_front_helper<n>(static_cast<Xs&&>(xs),
std::make_index_sequence<(n < len ? len - n : 0)>{});
}
};
template <>
struct is_empty_impl<ext::boost::tuple_tag> {
static constexpr auto apply(boost::tuples::null_type const&)
{ return hana::true_c; }
template <typename H, typename T>
static constexpr auto apply(boost::tuples::cons<H, T> const&)
{ return hana::false_c; }
};
//////////////////////////////////////////////////////////////////////////
// Foldable
//////////////////////////////////////////////////////////////////////////
template <>
struct length_impl<ext::boost::tuple_tag> {
template <typename Xs>
static constexpr auto apply(Xs const&) {
return hana::size_c<boost::tuples::length<Xs>::value>;
}
};
//////////////////////////////////////////////////////////////////////////
// Sequence
//////////////////////////////////////////////////////////////////////////
template <>
struct Sequence<ext::boost::tuple_tag> {
static constexpr bool value = true;
};
template <>
struct make_impl<ext::boost::tuple_tag> {
template <typename ...Xs>
static constexpr auto apply(Xs&& ...xs) {
return boost::tuples::tuple<
typename detail::decay<Xs>::type...
>{static_cast<Xs&&>(xs)...};
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_BOOST_TUPLE_HPP

View File

@ -0,0 +1,25 @@
/*!
@file
Includes all the adaptors for the standard library.
Copyright Louis Dionne 2013-2022
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_EXT_STD_HPP
#define BOOST_HANA_EXT_STD_HPP
//! @ingroup group-ext
//! @defgroup group-ext-std Standard library adapters
//! Adapters for components in the standard library.
#include <boost/hana/ext/std/array.hpp>
#include <boost/hana/ext/std/integer_sequence.hpp>
#include <boost/hana/ext/std/integral_constant.hpp>
#include <boost/hana/ext/std/pair.hpp>
#include <boost/hana/ext/std/ratio.hpp>
#include <boost/hana/ext/std/tuple.hpp>
#include <boost/hana/ext/std/vector.hpp>
#endif // !BOOST_HANA_EXT_STD_HPP

View File

@ -0,0 +1,171 @@
/*!
@file
Adapts `std::array` for use with Hana.
Copyright Louis Dionne 2013-2022
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_EXT_STD_ARRAY_HPP
#define BOOST_HANA_EXT_STD_ARRAY_HPP
#include <boost/hana/bool.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/algorithm.hpp>
#include <boost/hana/fwd/at.hpp>
#include <boost/hana/fwd/core/tag_of.hpp>
#include <boost/hana/fwd/drop_front.hpp>
#include <boost/hana/fwd/equal.hpp>
#include <boost/hana/fwd/is_empty.hpp>
#include <boost/hana/fwd/length.hpp>
#include <boost/hana/fwd/less.hpp>
#include <boost/hana/integral_constant.hpp>
#include <array>
#include <cstddef>
#include <type_traits>
#include <utility>
#ifdef BOOST_HANA_DOXYGEN_INVOKED
namespace std {
//! @ingroup group-ext-std
//! Adaptation of `std::array` for Hana.
//!
//!
//!
//! Modeled concepts
//! ----------------
//! 1. `Comparable`\n
//! `std::array`s are compared as per `std::equal`, except that two arrays
//! with different sizes compare unequal instead of triggering an error
//! and the result of the comparison is `constexpr` if both arrays are
//! `constexpr`.
//! @include example/ext/std/array/comparable.cpp
//!
//! 2. `Orderable`\n
//! `std::array`s are ordered with the usual lexicographical ordering,
//! except that two arrays with different size can be ordered instead
//! of triggering an error and the result of the comparison is `constexpr`
//! if both arrays are `constexpr`.
//! @include example/ext/std/array/orderable.cpp
//!
//! 3. `Foldable`\n
//! Folding an array from the left is equivalent to calling
//! `std::accumulate` on it, except it can be `constexpr`.
//! @include example/ext/std/array/foldable.cpp
//!
//! 4. `Iterable`\n
//! Iterating over a `std::array` is equivalent to iterating over it with
//! a normal `for` loop.
//! @include example/ext/std/array/iterable.cpp
template <typename T, std::size_t N>
struct array { };
}
#endif
namespace boost { namespace hana {
namespace ext { namespace std { struct array_tag; }}
template <typename T, std::size_t N>
struct tag_of<std::array<T, N>> {
using type = ext::std::array_tag;
};
//////////////////////////////////////////////////////////////////////////
// Foldable
//////////////////////////////////////////////////////////////////////////
template <>
struct length_impl<ext::std::array_tag> {
template <typename Xs>
static constexpr auto apply(Xs const&) {
return hana::size_c<std::tuple_size<Xs>::type::value>;
}
};
//////////////////////////////////////////////////////////////////////////
// Iterable
//////////////////////////////////////////////////////////////////////////
template <>
struct at_impl<ext::std::array_tag> {
template <typename Xs, typename N>
static constexpr decltype(auto) apply(Xs&& xs, N const&) {
constexpr std::size_t n = N::value;
return std::get<n>(static_cast<Xs&&>(xs));
}
};
template <>
struct drop_front_impl<ext::std::array_tag> {
template <std::size_t n, typename Xs, std::size_t ...i>
static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
using T = typename std::remove_reference<Xs>::type::value_type;
return std::array<T, sizeof...(i)>{{static_cast<Xs&&>(xs)[n + i]...}};
}
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 = std::tuple_size<
typename std::remove_cv<
typename std::remove_reference<Xs>::type
>::type
>::value;
return drop_front_helper<n>(static_cast<Xs&&>(xs),
std::make_index_sequence<(n < len ? len - n : 0)>{});
}
};
template <>
struct is_empty_impl<ext::std::array_tag> {
template <typename T, std::size_t N>
static constexpr auto apply(std::array<T, N> const&) {
return hana::bool_c<N == 0>;
}
};
//////////////////////////////////////////////////////////////////////////
// Comparable
//////////////////////////////////////////////////////////////////////////
template <>
struct equal_impl<ext::std::array_tag, ext::std::array_tag> {
template <typename T, std::size_t n, typename U>
static constexpr bool apply(std::array<T, n> const& xs, std::array<U, n> const& ys)
{ return detail::equal(&xs[0], &xs[0] + n, &ys[0], &ys[0] + n); }
template <typename T, typename U>
static constexpr auto apply(std::array<T, 0> const&, std::array<U, 0> const&)
{ return hana::true_c; }
template <typename T, std::size_t n, typename U, std::size_t m>
static constexpr auto apply(std::array<T, n> const&, std::array<U, m> const&)
{ return hana::false_c; }
};
//////////////////////////////////////////////////////////////////////////
// Orderable
//////////////////////////////////////////////////////////////////////////
template <>
struct less_impl<ext::std::array_tag, ext::std::array_tag> {
template <typename T, std::size_t n, typename U, std::size_t m>
static constexpr auto apply(std::array<T, n> const& xs, std::array<U, m> const& ys) {
// This logic is more complex than it needs to be because we can't
// use `.begin()` and `.end()`, which are not constexpr in C++14,
// and because `&arr[0]` is UB when the array is empty.
if (xs.empty()) {
return !ys.empty();
} else {
if (ys.empty()) {
return false;
} else {
return detail::lexicographical_compare(&xs[0], &xs[0] + n,
&ys[0], &ys[0] + m);
}
}
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_STD_ARRAY_HPP

View File

@ -0,0 +1,140 @@
/*!
@file
Adapts `std::integer_sequence` for use with Hana.
Copyright Louis Dionne 2013-2022
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_EXT_STD_INTEGER_SEQUENCE_HPP
#define BOOST_HANA_EXT_STD_INTEGER_SEQUENCE_HPP
#include <boost/hana/bool.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/fast_and.hpp>
#include <boost/hana/ext/std/integral_constant.hpp>
#include <boost/hana/fwd/at.hpp>
#include <boost/hana/fwd/core/tag_of.hpp>
#include <boost/hana/fwd/drop_front.hpp>
#include <boost/hana/fwd/equal.hpp>
#include <boost/hana/fwd/is_empty.hpp>
#include <boost/hana/fwd/unpack.hpp>
#include <cstddef>
#include <type_traits>
#include <utility>
#ifdef BOOST_HANA_DOXYGEN_INVOKED
namespace std {
//! @ingroup group-ext-std
//! Adaptation of `std::integer_sequence` for Hana.
//!
//!
//!
//! Modeled concepts
//! ----------------
//! 1. `Comparable`\n
//! Two `std::integer_sequence`s are equal if and only if they have the
//! same number of elements, and if corresponding elements compare equal.
//! The types of the elements held in both `integer_sequence`s may be
//! different, as long as they can be compared.
//! @include example/ext/std/integer_sequence/comparable.cpp
//!
//! 2. `Foldable`\n
//! Folding an `integer_sequence` is equivalent to folding a sequence of
//! `std::integral_constant`s with the corresponding types.
//! @include example/ext/std/integer_sequence/foldable.cpp
//!
//! 3. `Iterable`\n
//! Iterating over an `integer_sequence` is equivalent to iterating over
//! a sequence of the corresponding `std::integral_constant`s.
//! @include example/ext/std/integer_sequence/iterable.cpp
//!
//! 4. `Searchable`\n
//! Searching through an `integer_sequence` is equivalent to searching
//! through the corresponding sequence of `std::integral_constant`s.
//! @include example/ext/std/integer_sequence/searchable.cpp
template <typename T, T ...v>
struct integer_sequence { };
}
#endif
namespace boost { namespace hana {
namespace ext { namespace std { struct integer_sequence_tag; }}
template <typename T, T ...v>
struct tag_of<std::integer_sequence<T, v...>> {
using type = ext::std::integer_sequence_tag;
};
//////////////////////////////////////////////////////////////////////////
// Comparable
//////////////////////////////////////////////////////////////////////////
template <>
struct equal_impl<ext::std::integer_sequence_tag, ext::std::integer_sequence_tag> {
template <typename X, X ...xs, typename Y, Y ...ys>
static constexpr hana::bool_<detail::fast_and<(xs == ys)...>::value>
apply(std::integer_sequence<X, xs...> const&, std::integer_sequence<Y, ys...> const&)
{ return {}; }
template <typename Xs, typename Ys>
static constexpr hana::false_ apply(Xs const&, Ys const&, ...)
{ return {}; }
};
//////////////////////////////////////////////////////////////////////////
// Foldable
//////////////////////////////////////////////////////////////////////////
template <>
struct unpack_impl<ext::std::integer_sequence_tag> {
template <typename T, T ...v, typename F>
static constexpr decltype(auto)
apply(std::integer_sequence<T, v...> const&, F&& f) {
return static_cast<F&&>(f)(std::integral_constant<T, v>{}...);
}
};
//////////////////////////////////////////////////////////////////////////
// Iterable
//////////////////////////////////////////////////////////////////////////
template <>
struct at_impl<ext::std::integer_sequence_tag> {
template <typename T, T ...v, typename N>
static constexpr auto apply(std::integer_sequence<T, v...> const&, N const&) {
constexpr std::size_t n = N::value;
constexpr T values_[] = {v...};
return std::integral_constant<T, values_[n]>{};
}
};
template <>
struct drop_front_impl<ext::std::integer_sequence_tag> {
template <std::size_t n, typename T, T ...t, std::size_t ...i>
static constexpr auto drop_front_helper(std::integer_sequence<T, t...>,
std::index_sequence<i...>)
{
constexpr T ts[sizeof...(t)+1] = {t...}; // avoid 0-sized array
return std::integer_sequence<T, ts[n + i]...>{};
}
template <typename T, T ...t, typename N>
static constexpr auto apply(std::integer_sequence<T, t...> ts, N const&) {
constexpr std::size_t n = N::value;
constexpr std::size_t len = sizeof...(t);
return drop_front_helper<n>(ts,
std::make_index_sequence<(n < len ? len - n : 0)>{});
}
};
template <>
struct is_empty_impl<ext::std::integer_sequence_tag> {
template <typename T, T ...xs>
static constexpr auto apply(std::integer_sequence<T, xs...> const&)
{ return hana::bool_c<sizeof...(xs) == 0>; }
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_STD_INTEGER_SEQUENCE_HPP

View File

@ -0,0 +1,96 @@
/*!
@file
Adapts `std::integral_constant` for use with Hana.
Copyright Louis Dionne 2013-2022
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_EXT_STD_INTEGRAL_CONSTANT_HPP
#define BOOST_HANA_EXT_STD_INTEGRAL_CONSTANT_HPP
#include <boost/hana/concept/integral_constant.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/fwd/core/to.hpp>
#include <boost/hana/fwd/core/tag_of.hpp>
#include <boost/hana/fwd/integral_constant.hpp>
#include <type_traits>
#ifdef BOOST_HANA_DOXYGEN_INVOKED
namespace std {
//! @ingroup group-ext-std
//! Adapter for `std::integral_constant`s.
//!
//! Provided models
//! ---------------
//! 1. `Constant` and `IntegralConstant`\n
//! A `std::integral_constant` is a model of the `IntegralConstant` and
//! `Constant` concepts, just like `hana::integral_constant`s are. As a
//! consequence, they are also implicitly a model of the concepts provided
//! for all models of `Constant`.
//! @include example/ext/std/integral_constant.cpp
template <typename T, T v>
struct integral_constant { };
}
#endif
namespace boost { namespace hana {
namespace ext { namespace std {
template <typename T>
struct integral_constant_tag { using value_type = T; };
}}
namespace detail {
template <typename T, T v>
constexpr bool
is_std_integral_constant(std::integral_constant<T, v>*)
{ return true; }
constexpr bool is_std_integral_constant(...)
{ return false; }
template <typename T, T v>
constexpr bool
is_hana_integral_constant(hana::integral_constant<T, v>*)
{ return true; }
constexpr bool is_hana_integral_constant(...)
{ return false; }
}
template <typename T>
struct tag_of<T, when<
detail::is_std_integral_constant((T*)0) &&
!detail::is_hana_integral_constant((T*)0)
>> {
using type = ext::std::integral_constant_tag<
typename hana::tag_of<typename T::value_type>::type
>;
};
//////////////////////////////////////////////////////////////////////////
// Constant/IntegralConstant
//////////////////////////////////////////////////////////////////////////
template <typename T>
struct IntegralConstant<ext::std::integral_constant_tag<T>> {
static constexpr bool value = true;
};
template <typename T, typename C>
struct to_impl<ext::std::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 std::integral_constant<T, N::value>{};
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_STD_INTEGRAL_CONSTANT_HPP

View File

@ -0,0 +1,91 @@
/*!
@file
Adapts `std::pair` for use with Hana.
Copyright Louis Dionne 2013-2022
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_EXT_STD_PAIR_HPP
#define BOOST_HANA_EXT_STD_PAIR_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/fwd/core/make.hpp>
#include <boost/hana/fwd/core/tag_of.hpp>
#include <boost/hana/fwd/first.hpp>
#include <boost/hana/fwd/second.hpp>
#include <utility>
#ifdef BOOST_HANA_DOXYGEN_INVOKED
namespace std {
//! @ingroup group-ext-std
//! Adaptation of `std::pair` for Hana.
//!
//!
//! Modeled concepts
//! ----------------
//! A `std::pair` models exactly the same concepts as a `hana::pair`.
//! Please refer to the documentation of `hana::pair` for details.
//!
//! @include example/ext/std/pair.cpp
template <typename First, typename Second>
struct pair { };
}
#endif
namespace boost { namespace hana {
namespace ext { namespace std { struct pair_tag; }}
template <typename First, typename Second>
struct tag_of<std::pair<First, Second>> {
using type = ext::std::pair_tag;
};
//////////////////////////////////////////////////////////////////////////
// Product
//////////////////////////////////////////////////////////////////////////
template <>
struct make_impl<ext::std::pair_tag> {
template <typename X, typename Y>
static constexpr decltype(auto) apply(X&& x, Y&& y) {
return std::make_pair(static_cast<X&&>(x),
static_cast<Y&&>(y));
}
};
template <>
struct first_impl<ext::std::pair_tag> {
template <typename T, typename U>
static constexpr T const& apply(std::pair<T, U> const& p)
{ return p.first; }
template <typename T, typename U>
static constexpr T& apply(std::pair<T, U>& p)
{ return p.first; }
template <typename T, typename U>
static constexpr T&& apply(std::pair<T, U>&& p)
{ return static_cast<T&&>(p.first); }
};
template <>
struct second_impl<ext::std::pair_tag> {
template <typename T, typename U>
static constexpr U const& apply(std::pair<T, U> const& p)
{ return p.second; }
template <typename T, typename U>
static constexpr U& apply(std::pair<T, U>& p)
{ return p.second; }
template <typename T, typename U>
static constexpr U&& apply(std::pair<T, U>&& p)
{ return static_cast<U&&>(p.second); }
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_STD_PAIR_HPP

View File

@ -0,0 +1,164 @@
/*!
@file
Adapts `std::ratio` for use with Hana.
Copyright Louis Dionne 2013-2022
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_EXT_STD_RATIO_HPP
#define BOOST_HANA_EXT_STD_RATIO_HPP
#include <boost/hana/bool.hpp>
#include <boost/hana/concept/integral_constant.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/fwd/core/to.hpp>
#include <boost/hana/fwd/core/tag_of.hpp>
#include <boost/hana/fwd/div.hpp>
#include <boost/hana/fwd/equal.hpp>
#include <boost/hana/fwd/less.hpp>
#include <boost/hana/fwd/minus.hpp>
#include <boost/hana/fwd/mod.hpp>
#include <boost/hana/fwd/mult.hpp>
#include <boost/hana/fwd/one.hpp>
#include <boost/hana/fwd/plus.hpp>
#include <boost/hana/fwd/zero.hpp>
#include <cstdint>
#include <ratio>
#include <type_traits>
#ifdef BOOST_HANA_DOXYGEN_INVOKED
namespace std {
//! @ingroup group-ext-std
//! Adaptation of `std::ratio` for Hana.
//!
//!
//! Modeled concepts
//! ----------------
//! 1. `Comparable`\n
//! `std::ratio`s are compared for equality using `std::ratio_equal`.
//! @include example/ext/std/ratio/comparable.cpp
//!
//! 2. `Orderable`\n
//! `std::ratio`s are ordered using `std::ratio_less`.
//! @include example/ext/std/ratio/orderable.cpp
//!
//! 3. `Monoid`, `Group`, `Ring`, and `EuclideanRing`\n
//! `std::ratio`s are added, subtracted, multiplied and divided using
//! `std::ratio_add`, `std::ratio_subtract`, `std::ratio_multiply` and
//! `std::ratio_divide`, respectively. Furthermore, the neutral element
//! for the additive operation is `std::ratio<0, 1>{}`, and the neutral
//! element for the multiplicative operation is `std::ratio<1, 1>{}`.
//! @include example/ext/std/ratio/arithmetic.cpp
template <std::intmax_t Num, std::intmax_t Denom>
class ratio { };
}
#endif
namespace boost { namespace hana {
namespace ext { namespace std { struct ratio_tag; }}
template <std::intmax_t num, std::intmax_t den>
struct tag_of<std::ratio<num, den>> {
using type = ext::std::ratio_tag;
};
//////////////////////////////////////////////////////////////////////////
// Conversion from IntegralConstants
//////////////////////////////////////////////////////////////////////////
template <typename C>
struct to_impl<ext::std::ratio_tag, C, when<
hana::IntegralConstant<C>::value
>> {
template <typename N>
static constexpr auto apply(N const&) {
return std::ratio<N::value>{};
}
};
//////////////////////////////////////////////////////////////////////////
// Comparable
//////////////////////////////////////////////////////////////////////////
template <>
struct equal_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
template <typename R1, typename R2>
static constexpr auto apply(R1 const&, R2 const&)
{ return hana::bool_c<std::ratio_equal<R1, R2>::value>; }
};
//////////////////////////////////////////////////////////////////////////
// Orderable
//////////////////////////////////////////////////////////////////////////
template <>
struct less_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
template <typename R1, typename R2>
static constexpr auto apply(R1 const&, R2 const&)
{ return hana::bool_c<std::ratio_less<R1, R2>::value>; }
};
//////////////////////////////////////////////////////////////////////////
// Monoid
//////////////////////////////////////////////////////////////////////////
template <>
struct plus_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
template <typename R1, typename R2>
static constexpr std::ratio_add<R1, R2> apply(R1 const&, R2 const&)
{ return {}; }
};
template <>
struct zero_impl<ext::std::ratio_tag> {
static constexpr std::ratio<0> apply()
{ return {}; }
};
//////////////////////////////////////////////////////////////////////////
// Group
//////////////////////////////////////////////////////////////////////////
template <>
struct minus_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
template <typename R1, typename R2>
static constexpr std::ratio_subtract<R1, R2> apply(R1 const&, R2 const&)
{ return {}; }
};
//////////////////////////////////////////////////////////////////////////
// Ring
//////////////////////////////////////////////////////////////////////////
template <>
struct mult_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
template <typename R1, typename R2>
static constexpr std::ratio_multiply<R1, R2> apply(R1 const&, R2 const&)
{ return {}; }
};
template <>
struct one_impl<ext::std::ratio_tag> {
static constexpr std::ratio<1> apply()
{ return {}; }
};
//////////////////////////////////////////////////////////////////////////
// EuclideanRing
//////////////////////////////////////////////////////////////////////////
template <>
struct div_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
template <typename R1, typename R2>
static constexpr std::ratio_divide<R1, R2> apply(R1 const&, R2 const&)
{ return {}; }
};
template <>
struct mod_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
template <typename R1, typename R2>
static constexpr std::ratio<0> apply(R1 const&, R2 const&)
{ return {}; }
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_STD_RATIO_HPP

View File

@ -0,0 +1,180 @@
/*!
@file
Adapts `std::tuple` for use with Hana.
Copyright Louis Dionne 2013-2022
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_EXT_STD_TUPLE_HPP
#define BOOST_HANA_EXT_STD_TUPLE_HPP
#include <boost/hana/bool.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <boost/hana/fwd/at.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/empty.hpp>
#include <boost/hana/fwd/flatten.hpp>
#include <boost/hana/fwd/front.hpp>
#include <boost/hana/fwd/is_empty.hpp>
#include <boost/hana/fwd/length.hpp>
#include <boost/hana/fwd/lift.hpp>
#include <boost/hana/integral_constant.hpp>
#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>
#ifdef BOOST_HANA_DOXYGEN_INVOKED
namespace std {
//! @ingroup group-ext-std
//! Adapter for `std::tuple`s.
//!
//!
//! Modeled concepts
//! ----------------
//! A `std::tuple` is a model of the `Sequence` concept, and all the
//! concepts it refines. That makes it essentially the same as a Hana
//! tuple, although the complexity of some operations might differ from
//! that of Hana's tuple.
//!
//! @include example/ext/std/tuple.cpp
template <typename ...T>
struct tuple { };
}
#endif
namespace boost { namespace hana {
namespace ext { namespace std { struct tuple_tag; }}
template <typename ...Xs>
struct tag_of<std::tuple<Xs...>> {
using type = ext::std::tuple_tag;
};
//////////////////////////////////////////////////////////////////////////
// make
//////////////////////////////////////////////////////////////////////////
template <>
struct make_impl<ext::std::tuple_tag> {
template <typename ...Xs>
static constexpr decltype(auto) apply(Xs&& ...xs) {
return std::make_tuple(static_cast<Xs&&>(xs)...);
}
};
//////////////////////////////////////////////////////////////////////////
// Applicative
//////////////////////////////////////////////////////////////////////////
template <>
struct lift_impl<ext::std::tuple_tag> {
template <typename X>
static constexpr auto apply(X&& x) {
return std::tuple<typename detail::decay<X>::type>{
static_cast<X&&>(x)};
}
};
//////////////////////////////////////////////////////////////////////////
// Monad
//////////////////////////////////////////////////////////////////////////
template <>
struct flatten_impl<ext::std::tuple_tag> {
template <typename Xs, std::size_t ...i>
static constexpr decltype(auto)
flatten_helper(Xs&& xs, std::index_sequence<i...>) {
return std::tuple_cat(std::get<i>(static_cast<Xs&&>(xs))...);
}
template <typename Xs>
static constexpr decltype(auto) apply(Xs&& xs) {
using Raw = typename std::remove_reference<Xs>::type;
constexpr std::size_t Length = std::tuple_size<Raw>::value;
return flatten_helper(static_cast<Xs&&>(xs),
std::make_index_sequence<Length>{});
}
};
//////////////////////////////////////////////////////////////////////////
// MonadPlus
//////////////////////////////////////////////////////////////////////////
template <>
struct empty_impl<ext::std::tuple_tag> {
static constexpr auto apply()
{ return std::tuple<>{}; }
};
//////////////////////////////////////////////////////////////////////////
// Iterable
//////////////////////////////////////////////////////////////////////////
template <>
struct front_impl<ext::std::tuple_tag> {
template <typename Xs>
static constexpr decltype(auto) apply(Xs&& xs) {
return std::get<0>(static_cast<Xs&&>(xs));
}
};
template <>
struct drop_front_impl<ext::std::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 std::make_tuple(
hana::at_c<n + i>(static_cast<Xs&&>(xs))...
);
}
template <typename Xs, typename N>
static constexpr auto apply(Xs&& xs, N const&) {
using Raw = typename std::remove_reference<Xs>::type;
constexpr std::size_t n = N::value;
constexpr auto len = std::tuple_size<Raw>::value;
return drop_front_helper<n>(static_cast<Xs&&>(xs),
std::make_index_sequence<(n < len ? len - n : 0)>{});
}
};
template <>
struct is_empty_impl<ext::std::tuple_tag> {
template <typename ...Xs>
static constexpr auto apply(std::tuple<Xs...> const&)
{ return hana::bool_c<sizeof...(Xs) == 0>; }
};
template <>
struct at_impl<ext::std::tuple_tag> {
template <typename Xs, typename N>
static constexpr decltype(auto) apply(Xs&& xs, N const&) {
constexpr std::size_t index = N::value;
return std::get<index>(static_cast<Xs&&>(xs));
}
};
//////////////////////////////////////////////////////////////////////////
// Foldable
//////////////////////////////////////////////////////////////////////////
template <>
struct length_impl<ext::std::tuple_tag> {
template <typename ...Xs>
static constexpr auto apply(std::tuple<Xs...> const&) {
return hana::size_c<sizeof...(Xs)>;
}
};
//////////////////////////////////////////////////////////////////////////
// Sequence
//////////////////////////////////////////////////////////////////////////
template <>
struct Sequence<ext::std::tuple_tag> {
static constexpr bool value = true;
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_STD_TUPLE_HPP

View File

@ -0,0 +1,110 @@
/*!
@file
Adapts `std::vector` for use with Hana.
Copyright Louis Dionne 2013-2022
Copyright Gonzalo Brito Gadeschi 2015
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_EXT_STD_VECTOR_HPP
#define BOOST_HANA_EXT_STD_VECTOR_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/fwd/core/tag_of.hpp>
#include <boost/hana/less.hpp>
#include <algorithm>
#include <iterator>
#include <memory>
#include <type_traits>
#include <utility>
#include <vector>
namespace boost { namespace hana {
namespace ext { namespace std { struct vector_tag; }}
template <typename T, typename Allocator>
struct tag_of<std::vector<T, Allocator>> {
using type = ext::std::vector_tag;
};
//////////////////////////////////////////////////////////////////////////
// Comparable
//////////////////////////////////////////////////////////////////////////
template <>
struct equal_impl<ext::std::vector_tag, ext::std::vector_tag> {
template <typename T1, typename A1, typename T2, typename A2>
static bool apply(std::vector<T1, A1> const& v1,
std::vector<T2, A2> const& v2)
{
return std::equal(begin(v1), end(v1),
begin(v2), end(v2),
hana::equal);
}
};
//////////////////////////////////////////////////////////////////////////
// Orderable
//////////////////////////////////////////////////////////////////////////
template <>
struct less_impl<ext::std::vector_tag, ext::std::vector_tag> {
template <typename T1, typename A1, typename T2, typename A2>
static bool apply(std::vector<T1, A1> const& v1,
std::vector<T2, A2> const& v2)
{
return std::lexicographical_compare(begin(v1), end(v1),
begin(v2), end(v2),
hana::less);
}
};
#if 0
//////////////////////////////////////////////////////////////////////////
// Functor
//////////////////////////////////////////////////////////////////////////
template <>
struct transform_impl<ext::std::vector_tag> {
template <typename V, typename F>
static auto apply(V&& v, F&& f) {
using U = std::remove_cv_t<std::remove_reference_t<
decltype(f(*v.begin()))
>>;
using Alloc = typename std::remove_reference_t<V>::allocator_type;
using NewAlloc = typename std::allocator_traits<Alloc>::
template rebind_alloc<U>;
std::vector<U, NewAlloc> result; result.reserve(v.size());
std::transform(begin(v), end(v),
std::back_inserter(result), std::forward<F>(f));
return result;
}
template <typename T, typename Alloc, typename F>
static auto apply(std::vector<T, Alloc>&& v, F&& f)
-> std::enable_if_t<
std::is_same<
T,
std::remove_cv_t<std::remove_reference_t<
decltype(f(*v.begin()))
>>
>{}
, std::vector<T, Alloc>
>
{
// If we receive a rvalue and the function returns elements of
// the same type, we modify the vector in-place instead of
// returning a new one.
std::transform(std::make_move_iterator(begin(v)),
std::make_move_iterator(end(v)),
begin(v), std::forward<F>(f));
return std::move(v);
}
};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXT_STD_VECTOR_HPP

View File

@ -0,0 +1,50 @@
/*!
@file
Defines `boost::hana::extend`.
Copyright Louis Dionne 2013-2022
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_EXTEND_HPP
#define BOOST_HANA_EXTEND_HPP
#include <boost/hana/fwd/extend.hpp>
#include <boost/hana/concept/comonad.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/duplicate.hpp>
#include <boost/hana/transform.hpp>
namespace boost { namespace hana {
//! @cond
template <typename W_, typename F>
constexpr decltype(auto) extend_t::operator()(W_&& w, F&& f) const {
using W = typename hana::tag_of<W_>::type;
using Extend = BOOST_HANA_DISPATCH_IF(extend_impl<W>,
hana::Comonad<W>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Comonad<W>::value,
"hana::extend(w, f) requires 'w' to be a Comonad");
#endif
return Extend::apply(static_cast<W_&&>(w), static_cast<F&&>(f));
}
//! @endcond
template <typename W, bool condition>
struct extend_impl<W, when<condition>> : default_ {
template <typename X, typename F>
static constexpr decltype(auto) apply(X&& x, F&& f) {
return hana::transform(hana::duplicate(static_cast<X&&>(x)),
static_cast<F&&>(f));
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXTEND_HPP

View File

@ -0,0 +1,45 @@
/*!
@file
Defines `boost::hana::extract`.
Copyright Louis Dionne 2013-2022
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_EXTRACT_HPP
#define BOOST_HANA_EXTRACT_HPP
#include <boost/hana/fwd/extract.hpp>
#include <boost/hana/concept/comonad.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
namespace boost { namespace hana {
//! @cond
template <typename W_>
constexpr decltype(auto) extract_t::operator()(W_&& w) const {
using W = typename hana::tag_of<W_>::type;
using Extract = BOOST_HANA_DISPATCH_IF(extract_impl<W>,
hana::Comonad<W>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Comonad<W>::value,
"hana::extract(w) requires 'w' to be a Comonad");
#endif
return Extract::apply(static_cast<W_&&>(w));
}
//! @endcond
template <typename W, bool condition>
struct extract_impl<W, when<condition>> : default_ {
template <typename ...Args>
static constexpr auto apply(Args&& ...args) = delete;
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_EXTRACT_HPP

View File

@ -0,0 +1,74 @@
/*!
@file
Defines `boost::hana::fill`.
Copyright Louis Dionne 2013-2022
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_FILL_HPP
#define BOOST_HANA_FILL_HPP
#include <boost/hana/fwd/fill.hpp>
#include <boost/hana/concept/functor.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/functional/always.hpp>
#include <boost/hana/transform.hpp>
#include <boost/hana/unpack.hpp>
namespace boost { namespace hana {
//! @cond
template <typename Xs, typename Value>
constexpr auto fill_t::operator()(Xs&& xs, Value&& value) const {
using S = typename hana::tag_of<Xs>::type;
using Fill = BOOST_HANA_DISPATCH_IF(fill_impl<S>,
hana::Functor<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Functor<S>::value,
"hana::fill(xs, value) requires 'xs' to be a Functor");
#endif
return Fill::apply(static_cast<Xs&&>(xs),
static_cast<Value&&>(value));
}
//! @endcond
template <typename Fun, bool condition>
struct fill_impl<Fun, when<condition>> : default_ {
template <typename Xs, typename Value>
static constexpr auto apply(Xs&& xs, Value&& v) {
return hana::transform(static_cast<Xs&&>(xs),
hana::always(static_cast<Value&&>(v))
);
}
};
template <typename S>
struct fill_impl<S, when<Sequence<S>::value>> {
//! @cond
template <typename V>
struct filler {
V const& v;
template <typename ...Xs>
constexpr auto operator()(Xs const& ...xs) const {
return hana::make<S>(((void)xs, v)...);
}
};
//! @endcond
template <typename Xs, typename V>
static constexpr auto apply(Xs const& xs, V const& v) {
return hana::unpack(xs, filler<V>{v});
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_FILL_HPP

View File

@ -0,0 +1,135 @@
/*!
@file
Defines `boost::hana::filter`.
Copyright Louis Dionne 2013-2022
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_FILTER_HPP
#define BOOST_HANA_FILTER_HPP
#include <boost/hana/fwd/filter.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/bool.hpp>
#include <boost/hana/chain.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/algorithm.hpp>
#include <boost/hana/detail/array.hpp>
#include <boost/hana/detail/decay.hpp>
#include <boost/hana/empty.hpp>
#include <boost/hana/lift.hpp>
#include <boost/hana/unpack.hpp>
#include <cstddef>
#include <utility>
namespace boost { namespace hana {
//! @cond
template <typename Xs, typename Pred>
constexpr auto filter_t::operator()(Xs&& xs, Pred&& pred) const {
using M = typename hana::tag_of<Xs>::type;
using Filter = BOOST_HANA_DISPATCH_IF(filter_impl<M>,
hana::MonadPlus<M>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::MonadPlus<M>::value,
"hana::filter(xs, pred) requires 'xs' to be a MonadPlus");
#endif
return Filter::apply(static_cast<Xs&&>(xs),
static_cast<Pred&&>(pred));
}
//! @endcond
namespace detail {
template <typename Pred, typename M>
struct lift_or_empty {
template <typename X>
static constexpr auto helper(X&& x, hana::true_)
{ return hana::lift<M>(static_cast<X&&>(x)); }
template <typename X>
static constexpr auto helper(X&&, hana::false_)
{ return hana::empty<M>(); }
template <typename X>
constexpr auto operator()(X&& x) const {
constexpr bool cond = decltype(std::declval<Pred>()(x))::value;
return helper(static_cast<X&&>(x), hana::bool_c<cond>);
}
};
}
template <typename M, bool condition>
struct filter_impl<M, when<condition>> : default_ {
template <typename Xs, typename Pred>
static constexpr decltype(auto) apply(Xs&& xs, Pred const&) {
return hana::chain(static_cast<Xs&&>(xs),
detail::lift_or_empty<Pred, M>{}
);
}
};
namespace detail {
template <bool ...b>
struct filter_indices {
static constexpr auto compute_indices() {
constexpr bool bs[] = {b..., false}; // avoid empty array
constexpr std::size_t N = detail::count(bs, bs + sizeof(bs), true);
detail::array<std::size_t, N> indices{};
std::size_t* keep = &indices[0];
for (std::size_t i = 0; i < sizeof...(b); ++i)
if (bs[i])
*keep++ = i;
return indices;
}
static constexpr auto cached_indices = compute_indices();
};
template <typename Pred>
struct make_filter_indices {
Pred const& pred;
template <typename ...X>
auto operator()(X&& ...x) const -> filter_indices<
static_cast<bool>(detail::decay<
decltype(pred(static_cast<X&&>(x)))
>::type::value)...
> { return {}; }
};
}
template <typename S>
struct filter_impl<S, when<Sequence<S>::value>> {
template <typename Indices, typename Xs, std::size_t ...i>
static constexpr auto filter_helper(Xs&& xs, std::index_sequence<i...>) {
return hana::make<S>(
hana::at_c<Indices::cached_indices[i]>(static_cast<Xs&&>(xs))...
);
}
template <typename Xs, typename Pred>
static constexpr auto apply(Xs&& xs, Pred const& pred) {
using Indices = decltype(
hana::unpack(static_cast<Xs&&>(xs),
detail::make_filter_indices<Pred>{pred})
);
return filter_impl::filter_helper<Indices>(
static_cast<Xs&&>(xs),
std::make_index_sequence<Indices::cached_indices.size()>{}
);
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_FILTER_HPP

View File

@ -0,0 +1,61 @@
/*!
@file
Defines `boost::hana::find`.
Copyright Louis Dionne 2013-2022
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_FIND_HPP
#define BOOST_HANA_FIND_HPP
#include <boost/hana/fwd/find.hpp>
#include <boost/hana/concept/searchable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/find_if.hpp>
namespace boost { namespace hana {
//! @cond
template <typename Xs, typename Key>
constexpr auto find_t::operator()(Xs&& xs, Key const& key) const {
using S = typename hana::tag_of<Xs>::type;
using Find = BOOST_HANA_DISPATCH_IF(find_impl<S>,
hana::Searchable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Searchable<S>::value,
"hana::find(xs, key) requires 'xs' to be Searchable");
#endif
return Find::apply(static_cast<Xs&&>(xs), key);
}
//! @endcond
namespace 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);
}
};
}
template <typename S, bool condition>
struct find_impl<S, when<condition>> : default_ {
template <typename Xs, typename Key>
static constexpr auto apply(Xs&& xs, Key const& key) {
return hana::find_if(static_cast<Xs&&>(xs),
detail::equal_to<Key>{key});
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_FIND_HPP

View File

@ -0,0 +1,129 @@
/*!
@file
Defines `boost::hana::find_if`.
Copyright Louis Dionne 2013-2022
Copyright Jason Rice 2017
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_HANA_FIND_IF_HPP
#define BOOST_HANA_FIND_IF_HPP
#include <boost/hana/fwd/find_if.hpp>
#include <boost/hana/accessors.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/bool.hpp>
#include <boost/hana/concept/iterable.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/first.hpp>
#include <boost/hana/functional/compose.hpp>
#include <boost/hana/index_if.hpp>
#include <boost/hana/second.hpp>
#include <boost/hana/transform.hpp>
#include <cstddef>
#include <utility>
namespace boost { namespace hana {
//! @cond
template <typename Xs, typename Pred>
constexpr auto find_if_t::operator()(Xs&& xs, Pred&& pred) const {
using S = typename hana::tag_of<Xs>::type;
using FindIf = BOOST_HANA_DISPATCH_IF(find_if_impl<S>,
hana::Searchable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Searchable<S>::value,
"hana::find_if(xs, pred) requires 'xs' to be a Searchable");
#endif
return FindIf::apply(static_cast<Xs&&>(xs), static_cast<Pred&&>(pred));
}
//! @endcond
template <typename S, bool condition>
struct find_if_impl<S, when<condition>> : default_ {
template <typename ...Args>
static constexpr auto apply(Args&& ...) = delete;
};
namespace detail {
template <typename Xs>
struct partial_at {
Xs const& xs;
template <typename I>
constexpr decltype(auto) operator()(I i) const {
return hana::at(xs, i);
}
};
}
template <typename Tag>
struct find_if_impl<Tag, when<Iterable<Tag>::value>> {
template <typename Xs, typename Pred>
static constexpr auto apply(Xs&& xs, Pred&& pred) {
using Result = decltype(hana::index_if(
static_cast<Xs&&>(xs), static_cast<Pred&&>(pred)));
return hana::transform(Result{},
detail::partial_at<std::decay_t<Xs>>{static_cast<Xs&&>(xs)});
}
};
template <typename T, std::size_t N>
struct find_if_impl<T[N]> {
template <typename Xs>
static constexpr auto find_if_helper(Xs&&, hana::false_)
{ return hana::nothing; }
template <typename Xs>
static constexpr auto find_if_helper(Xs&& xs, hana::true_)
{ return hana::just(static_cast<Xs&&>(xs)[0]); }
template <typename Xs, typename Pred>
static constexpr auto apply(Xs&& xs, Pred&& pred) {
return find_if_helper(static_cast<Xs&&>(xs),
hana::bool_c<decltype(
static_cast<Pred&&>(pred)(static_cast<Xs&&>(xs)[0])
)::value>
);
}
};
namespace struct_detail {
template <typename X>
struct get_member {
X x;
template <typename Member>
constexpr decltype(auto) operator()(Member&& member) && {
return hana::second(static_cast<Member&&>(member))(
static_cast<X&&>(x)
);
}
};
}
template <typename S>
struct find_if_impl<S, when<hana::Struct<S>::value>> {
template <typename X, typename Pred>
static constexpr decltype(auto) apply(X&& x, Pred&& pred) {
return hana::transform(
hana::find_if(hana::accessors<S>(),
hana::compose(static_cast<Pred&&>(pred), hana::first)
),
struct_detail::get_member<X>{static_cast<X&&>(x)}
);
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_FIND_IF_HPP

View File

@ -0,0 +1,45 @@
/*!
@file
Defines `boost::hana::first`.
Copyright Louis Dionne 2013-2022
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_FIRST_HPP
#define BOOST_HANA_FIRST_HPP
#include <boost/hana/fwd/first.hpp>
#include <boost/hana/concept/product.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
namespace boost { namespace hana {
//! @cond
template <typename Pair>
constexpr decltype(auto) first_t::operator()(Pair&& pair) const {
using P = typename hana::tag_of<Pair>::type;
using First = BOOST_HANA_DISPATCH_IF(first_impl<P>,
hana::Product<P>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Product<P>::value,
"hana::first(pair) requires 'pair' to be a Product");
#endif
return First::apply(static_cast<Pair&&>(pair));
}
//! @endcond
template <typename P, bool condition>
struct first_impl<P, when<condition>> : default_ {
template <typename ...Args>
static constexpr auto apply(Args&& ...) = delete;
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_FIRST_HPP

View File

@ -0,0 +1,62 @@
/*!
@file
Defines `boost::hana::flatten`.
Copyright Louis Dionne 2013-2022
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_FLATTEN_HPP
#define BOOST_HANA_FLATTEN_HPP
#include <boost/hana/fwd/flatten.hpp>
#include <boost/hana/concept/monad.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/unpack_flatten.hpp>
#include <boost/hana/functional/id.hpp>
#include <boost/hana/fwd/chain.hpp>
#include <cstddef>
#include <utility>
namespace boost { namespace hana {
//! @cond
template <typename Xs>
constexpr auto flatten_t::operator()(Xs&& xs) const {
using M = typename hana::tag_of<Xs>::type;
using Flatten = BOOST_HANA_DISPATCH_IF(flatten_impl<M>,
hana::Monad<M>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Monad<M>::value,
"hana::flatten(xs) requires 'xs' to be a Monad");
#endif
return Flatten::apply(static_cast<Xs&&>(xs));
}
//! @endcond
template <typename M, bool condition>
struct flatten_impl<M, when<condition>> : default_ {
template <typename Xs>
static constexpr auto apply(Xs&& xs)
{ return hana::chain(static_cast<Xs&&>(xs), hana::id); }
};
template <typename S>
struct flatten_impl<S, when<Sequence<S>::value>> {
template <typename Xs>
static constexpr auto apply(Xs&& xs) {
return detail::unpack_flatten(static_cast<Xs&&>(xs), hana::make<S>);
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_FLATTEN_HPP

View File

@ -0,0 +1,17 @@
/*!
@file
Defines `boost::hana::fold`.
Copyright Louis Dionne 2013-2022
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_FOLD_HPP
#define BOOST_HANA_FOLD_HPP
#include <boost/hana/fwd/fold.hpp>
#include <boost/hana/fold_left.hpp>
#endif // !BOOST_HANA_FOLD_HPP

View File

@ -0,0 +1,97 @@
/*!
@file
Defines `boost::hana::fold_left`.
Copyright Louis Dionne 2013-2022
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_FOLD_LEFT_HPP
#define BOOST_HANA_FOLD_LEFT_HPP
#include <boost/hana/fwd/fold_left.hpp>
#include <boost/hana/concept/foldable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/detail/variadic/foldl1.hpp>
#include <boost/hana/functional/partial.hpp>
#include <boost/hana/unpack.hpp>
namespace boost { namespace hana {
//! @cond
template <typename Xs, typename State, typename F>
constexpr decltype(auto) fold_left_t::operator()(Xs&& xs, State&& state, F&& f) const {
using S = typename hana::tag_of<Xs>::type;
using FoldLeft = BOOST_HANA_DISPATCH_IF(fold_left_impl<S>,
hana::Foldable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Foldable<S>::value,
"hana::fold_left(xs, state, f) requires 'xs' to be Foldable");
#endif
return FoldLeft::apply(static_cast<Xs&&>(xs),
static_cast<State&&>(state),
static_cast<F&&>(f));
}
template <typename Xs, typename F>
constexpr decltype(auto) fold_left_t::operator()(Xs&& xs, F&& f) const {
using S = typename hana::tag_of<Xs>::type;
using FoldLeft = BOOST_HANA_DISPATCH_IF(fold_left_impl<S>,
hana::Foldable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Foldable<S>::value,
"hana::fold_left(xs, f) requires 'xs' to be Foldable");
#endif
return FoldLeft::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f));
}
//! @endcond
namespace detail {
template <typename F, typename State>
struct variadic_foldl1 {
F& f;
State& state;
template <typename ...T>
constexpr decltype(auto) operator()(T&& ...t) const {
return detail::variadic::foldl1(
static_cast<F&&>(f),
static_cast<State&&>(state),
static_cast<T&&>(t)...
);
}
};
}
template <typename T, bool condition>
struct fold_left_impl<T, when<condition>> : default_ {
// with state
template <typename Xs, typename S, typename F>
static constexpr decltype(auto) apply(Xs&& xs, S&& s, F&& f) {
return hana::unpack(static_cast<Xs&&>(xs),
detail::variadic_foldl1<F, S>{f, s}
);
}
// without state
template <typename Xs, typename F>
static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
return hana::unpack(static_cast<Xs&&>(xs),
hana::partial(
detail::variadic::foldl1,
static_cast<F&&>(f)
)
);
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_FOLD_LEFT_HPP

View File

@ -0,0 +1,97 @@
/*!
@file
Defines `boost::hana::fold_right`.
Copyright Louis Dionne 2013-2022
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_FOLD_RIGHT_HPP
#define BOOST_HANA_FOLD_RIGHT_HPP
#include <boost/hana/fwd/fold_right.hpp>
#include <boost/hana/concept/foldable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/detail/variadic/foldr1.hpp>
#include <boost/hana/functional/partial.hpp>
#include <boost/hana/fwd/unpack.hpp>
namespace boost { namespace hana {
//! @cond
template <typename Xs, typename State, typename F>
constexpr decltype(auto) fold_right_t::operator()(Xs&& xs, State&& state, F&& f) const {
using S = typename hana::tag_of<Xs>::type;
using FoldRight = BOOST_HANA_DISPATCH_IF(fold_right_impl<S>,
hana::Foldable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Foldable<S>::value,
"hana::fold_right(xs, state, f) requires 'xs' to be Foldable");
#endif
return FoldRight::apply(static_cast<Xs&&>(xs),
static_cast<State&&>(state),
static_cast<F&&>(f));
}
template <typename Xs, typename F>
constexpr decltype(auto) fold_right_t::operator()(Xs&& xs, F&& f) const {
using S = typename hana::tag_of<Xs>::type;
using FoldRight = BOOST_HANA_DISPATCH_IF(fold_right_impl<S>,
hana::Foldable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Foldable<S>::value,
"hana::fold_right(xs, f) requires 'xs' to be Foldable");
#endif
return FoldRight::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f));
}
//! @endcond
namespace detail {
template <typename F, typename State>
struct variadic_foldr {
F& f;
State& state;
template <typename ...T>
constexpr decltype(auto) operator()(T&& ...t) const {
return detail::variadic::foldr(
static_cast<F&&>(f),
static_cast<State&&>(state),
static_cast<T&&>(t)...
);
}
};
}
template <typename T, bool condition>
struct fold_right_impl<T, when<condition>> : default_ {
// with state
template <typename Xs, typename S, typename F>
static constexpr decltype(auto) apply(Xs&& xs, S&& s, F&& f) {
return hana::unpack(static_cast<Xs&&>(xs),
detail::variadic_foldr<F, S>{f, s}
);
}
// without state
template <typename Xs, typename F>
static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
return hana::unpack(static_cast<Xs&&>(xs),
hana::partial(
detail::variadic::foldr1,
static_cast<F&&>(f)
)
);
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_FOLD_RIGHT_HPP

View File

@ -0,0 +1,62 @@
/*!
@file
Defines `boost::hana::for_each`.
Copyright Louis Dionne 2013-2022
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_FOR_EACH_HPP
#define BOOST_HANA_FOR_EACH_HPP
#include <boost/hana/fwd/for_each.hpp>
#include <boost/hana/concept/foldable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
#include <boost/hana/unpack.hpp>
namespace boost { namespace hana {
//! @cond
template <typename Xs, typename F>
constexpr void for_each_t::operator()(Xs&& xs, F&& f) const {
using S = typename hana::tag_of<Xs>::type;
using ForEach = BOOST_HANA_DISPATCH_IF(for_each_impl<S>,
hana::Foldable<S>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Foldable<S>::value,
"hana::for_each(xs, f) requires 'xs' to be Foldable");
#endif
return ForEach::apply(static_cast<Xs&&>(xs), static_cast<F&&>(f));
}
//! @endcond
namespace detail {
template <typename F>
struct on_each {
F f;
template <typename ...Xs>
constexpr void operator()(Xs&& ...xs) const {
using Swallow = int[];
(void)Swallow{0, ((void)(*f)(static_cast<Xs&&>(xs)), 0)...};
}
};
}
template <typename T, bool condition>
struct for_each_impl<T, when<condition>> : default_ {
template <typename Xs, typename F>
static constexpr void apply(Xs&& xs, F&& f) {
// We use a pointer instead of a reference to avoid a Clang ICE.
hana::unpack(static_cast<Xs&&>(xs),
detail::on_each<decltype(&f)>{&f});
}
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_FOR_EACH_HPP

View File

@ -0,0 +1,47 @@
/*!
@file
Defines `boost::hana::front`.
Copyright Louis Dionne 2013-2022
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_FRONT_HPP
#define BOOST_HANA_FRONT_HPP
#include <boost/hana/fwd/front.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/concept/iterable.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/dispatch.hpp>
namespace boost { namespace hana {
//! @cond
template <typename Xs>
constexpr decltype(auto) front_t::operator()(Xs&& xs) const {
using It = typename hana::tag_of<Xs>::type;
using Front = BOOST_HANA_DISPATCH_IF(front_impl<It>,
hana::Iterable<It>::value
);
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::Iterable<It>::value,
"hana::front(xs) requires 'xs' to be an Iterable");
#endif
return Front::apply(static_cast<Xs&&>(xs));
}
//! @endcond
template <typename It, bool condition>
struct front_impl<It, when<condition>> : default_ {
template <typename Xs>
static constexpr decltype(auto) apply(Xs&& xs)
{ return hana::at_c<0>(static_cast<Xs&&>(xs)); }
};
}} // end namespace boost::hana
#endif // !BOOST_HANA_FRONT_HPP

View File

@ -0,0 +1,33 @@
/*!
@file
Defines the @ref group-functional module.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_HPP
#define BOOST_HANA_FUNCTIONAL_HPP
#include <boost/hana/functional/always.hpp>
#include <boost/hana/functional/apply.hpp>
#include <boost/hana/functional/arg.hpp>
#include <boost/hana/functional/capture.hpp>
#include <boost/hana/functional/compose.hpp>
#include <boost/hana/functional/curry.hpp>
#include <boost/hana/functional/demux.hpp>
#include <boost/hana/functional/fix.hpp>
#include <boost/hana/functional/flip.hpp>
#include <boost/hana/functional/id.hpp>
#include <boost/hana/functional/infix.hpp>
#include <boost/hana/functional/iterate.hpp>
#include <boost/hana/functional/lockstep.hpp>
#include <boost/hana/functional/on.hpp>
#include <boost/hana/functional/overload.hpp>
#include <boost/hana/functional/overload_linearly.hpp>
#include <boost/hana/functional/partial.hpp>
#include <boost/hana/functional/placeholder.hpp>
#include <boost/hana/functional/reverse_partial.hpp>
#endif // !BOOST_HANA_FUNCTIONAL_HPP

View File

@ -0,0 +1,64 @@
/*!
@file
Defines `boost::hana::always`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_ALWAYS_HPP
#define BOOST_HANA_FUNCTIONAL_ALWAYS_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/create.hpp>
#include <utility>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Return a constant function returning `x` regardless of the
//! argument(s) it is invoked with.
//!
//! Specifically, `always(x)` is a function such that
//! @code
//! always(x)(y...) == x
//! @endcode
//! for any `y...`. A copy of `x` is made and it is owned by the
//! `always(x)` function. When `always(x)` is called, it will return
//! a reference to the `x` it owns. This reference is valid as long
//! as `always(x)` is in scope.
//!
//!
//! ### Example
//! @include example/functional/always.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto always = [](auto&& x) {
return [perfect-capture](auto const& ...y) -> decltype(auto) {
return forwarded(x);
};
};
#else
template <typename T>
struct _always {
T val_;
template <typename ...Args>
constexpr T const& operator()(Args const& ...) const&
{ return val_; }
template <typename ...Args>
constexpr T& operator()(Args const& ...) &
{ return val_; }
template <typename ...Args>
constexpr T operator()(Args const& ...) &&
{ return std::move(val_); }
};
BOOST_HANA_INLINE_VARIABLE constexpr detail::create<_always> always{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_ALWAYS_HPP

View File

@ -0,0 +1,85 @@
/*!
@file
Defines `boost::hana::apply`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_APPLY_HPP
#define BOOST_HANA_FUNCTIONAL_APPLY_HPP
#include <boost/hana/config.hpp>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Invokes a Callable with the given arguments.
//!
//! This is equivalent to [std::invoke][1] that will be added in C++17.
//! However, `apply` is a function object instead of a function, which
//! makes it possible to pass it to higher-order algorithms.
//!
//!
//! @param f
//! A [Callable][2] to be invoked with the given arguments.
//!
//! @param x...
//! The arguments to call `f` with. The number of `x...` must match the
//! arity of `f`.
//!
//!
//! Example
//! -------
//! @include example/functional/apply.cpp
//!
//! [1]: http://en.cppreference.com/w/cpp/utility/functional/invoke
//! [2]: http://en.cppreference.com/w/cpp/named_req/Callable
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto apply = [](auto&& f, auto&& ...x) -> decltype(auto) {
return forwarded(f)(forwarded(x)...);
};
#else
struct apply_t {
template <typename F, typename... Args>
constexpr auto operator()(F&& f, Args&&... args) const ->
decltype(static_cast<F&&>(f)(static_cast<Args&&>(args)...))
{
return static_cast<F&&>(f)(static_cast<Args&&>(args)...);
}
template <typename Base, typename T, typename Derived>
constexpr auto operator()(T Base::*pmd, Derived&& ref) const ->
decltype(static_cast<Derived&&>(ref).*pmd)
{
return static_cast<Derived&&>(ref).*pmd;
}
template <typename PMD, typename Pointer>
constexpr auto operator()(PMD pmd, Pointer&& ptr) const ->
decltype((*static_cast<Pointer&&>(ptr)).*pmd)
{
return (*static_cast<Pointer&&>(ptr)).*pmd;
}
template <typename Base, typename T, typename Derived, typename... Args>
constexpr auto operator()(T Base::*pmf, Derived&& ref, Args&&... args) const ->
decltype((static_cast<Derived&&>(ref).*pmf)(static_cast<Args&&>(args)...))
{
return (static_cast<Derived&&>(ref).*pmf)(static_cast<Args&&>(args)...);
}
template <typename PMF, typename Pointer, typename... Args>
constexpr auto operator()(PMF pmf, Pointer&& ptr, Args&& ...args) const ->
decltype(((*static_cast<Pointer&&>(ptr)).*pmf)(static_cast<Args&&>(args)...))
{
return ((*static_cast<Pointer&&>(ptr)).*pmf)(static_cast<Args&&>(args)...);
}
};
BOOST_HANA_INLINE_VARIABLE constexpr apply_t apply{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_APPLY_HPP

View File

@ -0,0 +1,141 @@
/*!
@file
Defines `boost::hana::arg`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_ARG_HPP
#define BOOST_HANA_FUNCTIONAL_ARG_HPP
#include <boost/hana/config.hpp>
#include <cstddef>
#include <type_traits>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Return the `n`th passed argument.
//!
//! Specifically, `arg<n>(x1, ..., xn, ..., xm)` is equivalent to `xn`.
//! Note that indexing starts at 1, so `arg<1>` returns the 1st argument,
//! `arg<2>` the 2nd and so on. Using `arg<0>` is an error. Passing
//! less than `n` arguments to `arg<n>` is also an error.
//!
//!
//! @tparam n
//! An unsigned integer representing the argument to return. `n` must be
//! positive (meaning nonzero).
//!
//! @param x1, ..., xm
//! A variadic pack of arguments from which the `n`th one is returned.
//!
//!
//! @internal
//! ### Discussion: could `n` be dynamic?
//! We could have chosen `arg` to be used like `arg(n)(x...)` instead of
//! `arg<n>(x...)`. Provided all the arguments were of the same type, it
//! would then be possible for `n` to only be known at runtime. However,
//! we would then lose the ability to assert the in-boundedness of `n`
//! statically.
//!
//! ### Rationale for `n` being a non-type template parameter
//! I claim that the only interesting use case is with a compile-time
//! `n`, which means that the usage would become `arg(int_<n>)(x...)`,
//! which is more cumbersome to write than `arg<n>(x...)`. This is open
//! for discussion.
//! @endinternal
//!
//! ### Example
//! @include example/functional/arg.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
template <std::size_t n>
constexpr auto arg = [](auto&& x1, ..., auto&& xm) -> decltype(auto) {
return forwarded(xn);
};
#else
template <std::size_t n, typename = void>
struct arg_t;
template <>
struct arg_t<1> {
template <typename X1, typename ...Xn>
constexpr X1 operator()(X1&& x1, Xn&& ...) const
{ return static_cast<X1&&>(x1); }
};
template <>
struct arg_t<2> {
template <typename X1, typename X2, typename ...Xn>
constexpr X2 operator()(X1&&, X2&& x2, Xn&& ...) const
{ return static_cast<X2&&>(x2); }
};
template <>
struct arg_t<3> {
template <typename X1, typename X2, typename X3, typename ...Xn>
constexpr X3 operator()(X1&&, X2&&, X3&& x3, Xn&& ...) const
{ return static_cast<X3&&>(x3); }
};
template <>
struct arg_t<4> {
template <typename X1, typename X2, typename X3, typename X4, typename ...Xn>
constexpr X4 operator()(X1&&, X2&&, X3&&, X4&& x4, Xn&& ...) const
{ return static_cast<X4&&>(x4); }
};
template <>
struct arg_t<5> {
template <typename X1, typename X2, typename X3, typename X4,
typename X5, typename ...Xn>
constexpr X5 operator()(X1&&, X2&&, X3&&, X4&&, X5&& x5, Xn&& ...) const
{ return static_cast<X5&&>(x5); }
};
template <std::size_t n, typename>
struct arg_t {
static_assert(n > 0,
"invalid usage of boost::hana::arg<n> with n == 0");
template <typename X1, typename X2, typename X3, typename X4,
typename X5, typename ...Xn>
constexpr decltype(auto)
operator()(X1&&, X2&&, X3&&, X4&&, X5&&, Xn&& ...xn) const {
static_assert(sizeof...(xn) >= n - 5,
"invalid usage of boost::hana::arg<n> with too few arguments");
// Since compilers will typically try to continue for a bit after
// an error/static assertion, we must avoid sending the compiler
// in a very long computation if n == 0.
return arg_t<n == 0 ? 1 : n - 5>{}(static_cast<Xn&&>(xn)...);
}
};
template <std::size_t n>
struct arg_t<n, std::enable_if_t<(n > 25)>> {
template <
typename X1, typename X2, typename X3, typename X4, typename X5,
typename X6, typename X7, typename X8, typename X9, typename X10,
typename X11, typename X12, typename X13, typename X14, typename X15,
typename X16, typename X17, typename X18, typename X19, typename X20,
typename X21, typename X22, typename X23, typename X24, typename X25,
typename ...Xn>
constexpr decltype(auto)
operator()(X1&&, X2&&, X3&&, X4&&, X5&&,
X6&&, X7&&, X8&&, X9&&, X10&&,
X11&&, X12&&, X13&&, X14&&, X15&&,
X16&&, X17&&, X18&&, X19&&, X20&&,
X21&&, X22&&, X23&&, X24&&, X25&&, Xn&& ...xn) const
{ return arg_t<n - 25>{}(static_cast<Xn&&>(xn)...); }
};
template <std::size_t n>
BOOST_HANA_INLINE_VARIABLE constexpr arg_t<n> arg{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_ARG_HPP

View File

@ -0,0 +1,112 @@
/*!
@file
Defines `boost::hana::capture`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_CAPTURE_HPP
#define BOOST_HANA_FUNCTIONAL_CAPTURE_HPP
#include <boost/hana/basic_tuple.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <boost/hana/functional/partial.hpp>
#include <cstddef>
#include <utility>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Create a function capturing the given variables.
//!
//! Given 0 or more variables, `capture` creates a closure that can be
//! used to partially apply a function. This is very similar to `partial`,
//! except that `capture` allows the partially applied function to be
//! specified later. Specifically, `capture(vars...)` is a function object
//! taking a function `f` and returning `f` partially applied to `vars...`.
//! In other words,
//! @code
//! capture(vars...)(f)(args...) == f(vars..., args...)
//! @endcode
//!
//! @note
//! The arity of `f` must match the total number of arguments passed to
//! it, i.e. `sizeof...(vars) + sizeof...(args)`.
//!
//!
//! Example
//! -------
//! @include example/functional/capture.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto capture = [](auto&& ...variables) {
return [perfect-capture](auto&& f) {
return [perfect-capture](auto&& ...args) -> decltype(auto) {
return forwarded(f)(forwarded(variables)..., forwarded(args)...);
};
};
};
#else
namespace detail {
template <typename F, typename Closure, std::size_t ...i>
constexpr auto apply_capture(F&& f, Closure&& closure, std::index_sequence<i...>) {
return hana::partial(static_cast<F&&>(f),
hana::at_c<i>(static_cast<Closure&&>(closure).storage_)...
);
}
}
template <typename ...X>
struct capture_t;
struct make_capture_t {
struct secret { };
template <typename ...X>
constexpr capture_t<typename detail::decay<X>::type...>
operator()(X&& ...x) const {
return {secret{}, static_cast<X&&>(x)...};
}
};
template <typename ...X>
struct capture_t {
template <typename ...Y>
constexpr capture_t(make_capture_t::secret, Y&& ...y)
: storage_{static_cast<Y&&>(y)...}
{ }
basic_tuple<X...> storage_;
template <typename F>
constexpr auto operator()(F&& f) const& {
return detail::apply_capture(
static_cast<F&&>(f), *this,
std::make_index_sequence<sizeof...(X)>{}
);
}
template <typename F>
constexpr auto operator()(F&& f) & {
return detail::apply_capture(
static_cast<F&&>(f), *this,
std::make_index_sequence<sizeof...(X)>{}
);
}
template <typename F>
constexpr auto operator()(F&& f) && {
return detail::apply_capture(
static_cast<F&&>(f), static_cast<capture_t&&>(*this),
std::make_index_sequence<sizeof...(X)>{}
);
}
};
BOOST_HANA_INLINE_VARIABLE constexpr make_capture_t capture{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_CAPTURE_HPP

View File

@ -0,0 +1,108 @@
/*!
@file
Defines `boost::hana::compose`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_COMPOSE_HPP
#define BOOST_HANA_FUNCTIONAL_COMPOSE_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/create.hpp>
#include <boost/hana/detail/variadic/foldl1.hpp>
#include <utility>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Return the composition of two functions or more.
//!
//! `compose` is defined inductively. When given more than two functions,
//! `compose(f, g, h...)` is equivalent to `compose(f, compose(g, h...))`.
//! When given two functions, `compose(f, g)` is a function such that
//! @code
//! compose(f, g)(x, y...) == f(g(x), y...)
//! @endcode
//!
//! If you need composition of the form `f(g(x, y...))`, use `demux` instead.
//!
//! @note
//! `compose` is an associative operation; `compose(f, compose(g, h))`
//! is equivalent to `compose(compose(f, g), h)`.
//!
//! @internal
//! ### Proof of associativity
//!
//! @code
//! compose(f, compose(g, h))(x, xs...) == f(compose(g, h)(x), xs...)
//! == f(g(h(x)), xs...)
//!
//! compose(compose(f, g), h)(x, xs...) == compose(f, g)(h(x), xs...)
//! == f(g(h(x)), xs...)
//! @endcode
//! @endinternal
//!
//! ### Example
//! @include example/functional/compose.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto compose = [](auto&& f1, auto&& f2, ..., auto&& fn) {
return [perfect-capture](auto&& x, auto&& ...xs) -> decltype(auto) {
return forwarded(f1)(
forwarded(f2)(
...
forwarded(fn)(forwarded(x))
),
forwarded(xs)...
);
}
};
#else
template <typename F, typename G>
struct _compose {
F f; G g;
template <typename X, typename ...Xs>
constexpr decltype(auto) operator()(X&& x, Xs&& ...xs) const& {
return f(
g(static_cast<X&&>(x)),
static_cast<Xs&&>(xs)...
);
}
template <typename X, typename ...Xs>
constexpr decltype(auto) operator()(X&& x, Xs&& ...xs) & {
return f(
g(static_cast<X&&>(x)),
static_cast<Xs&&>(xs)...
);
}
template <typename X, typename ...Xs>
constexpr decltype(auto) operator()(X&& x, Xs&& ...xs) && {
return std::move(f)(
std::move(g)(static_cast<X&&>(x)),
static_cast<Xs&&>(xs)...
);
}
};
struct _make_compose {
template <typename F, typename G, typename ...H>
constexpr decltype(auto) operator()(F&& f, G&& g, H&& ...h) const {
return detail::variadic::foldl1(detail::create<_compose>{},
static_cast<F&&>(f),
static_cast<G&&>(g),
static_cast<H&&>(h)...
);
}
};
BOOST_HANA_INLINE_VARIABLE constexpr _make_compose compose{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_COMPOSE_HPP

View File

@ -0,0 +1,170 @@
/*!
@file
Defines `boost::hana::curry`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_CURRY_HPP
#define BOOST_HANA_FUNCTIONAL_CURRY_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <boost/hana/functional/apply.hpp>
#include <boost/hana/functional/partial.hpp>
#include <cstddef>
#include <type_traits>
#include <utility>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Curry a function up to the given number of arguments.
//!
//! [Currying][Wikipedia.currying] is a technique in which we consider a
//! function taking multiple arguments (or, equivalently, a tuple of
//! arguments), and turn it into a function which takes a single argument
//! and returns a function to handle the remaining arguments. To help
//! visualize, let's denote the type of a function `f` which takes
//! arguments of types `X1, ..., Xn` and returns a `R` as
//! @code
//! (X1, ..., Xn) -> R
//! @endcode
//!
//! Then, currying is the process of taking `f` and turning it into an
//! equivalent function (call it `g`) of type
//! @code
//! X1 -> (X2 -> (... -> (Xn -> R)))
//! @endcode
//!
//! This gives us the following equivalence, where `x1`, ..., `xn` are
//! objects of type `X1`, ..., `Xn` respectively:
//! @code
//! f(x1, ..., xn) == g(x1)...(xn)
//! @endcode
//!
//! Currying can be useful in several situations, especially when working
//! with higher-order functions.
//!
//! This `curry` utility is an implementation of currying in C++.
//! Specifically, `curry<n>(f)` is a function such that
//! @code
//! curry<n>(f)(x1)...(xn) == f(x1, ..., xn)
//! @endcode
//!
//! Note that the `n` has to be specified explicitly because the existence
//! of functions with variadic arguments in C++ make it impossible to know
//! when currying should stop.
//!
//! Unlike usual currying, this implementation also allows a curried
//! function to be called with several arguments at a time. Hence, the
//! following always holds
//! @code
//! curry<n>(f)(x1, ..., xk) == curry<n - k>(f)(x1)...(xk)
//! @endcode
//!
//! Of course, this requires `k` to be less than or equal to `n`; failure
//! to satisfy this will trigger a static assertion. This syntax is
//! supported because it makes curried functions usable where normal
//! functions are expected.
//!
//! Another "extension" is that `curry<0>(f)` is supported: `curry<0>(f)`
//! is a nullary function; whereas the classical definition for currying
//! seems to leave this case undefined, as nullary functions don't make
//! much sense in purely functional languages.
//!
//!
//! Example
//! -------
//! @include example/functional/curry.cpp
//!
//!
//! [Wikipedia.currying]: http://en.wikipedia.org/wiki/Currying
#ifdef BOOST_HANA_DOXYGEN_INVOKED
template <std::size_t n>
constexpr auto curry = [](auto&& f) {
return [perfect-capture](auto&& x1) {
return [perfect-capture](auto&& x2) {
...
return [perfect-capture](auto&& xn) -> decltype(auto) {
return forwarded(f)(
forwarded(x1), forwarded(x2), ..., forwarded(xn)
);
};
};
};
};
#else
template <std::size_t n, typename F>
struct curry_t;
template <std::size_t n>
struct make_curry_t {
template <typename F>
constexpr curry_t<n, typename detail::decay<F>::type>
operator()(F&& f) const { return {static_cast<F&&>(f)}; }
};
template <std::size_t n>
BOOST_HANA_INLINE_VARIABLE constexpr make_curry_t<n> curry{};
namespace curry_detail { namespace {
template <std::size_t n>
constexpr make_curry_t<n> curry_or_call{};
template <>
constexpr auto curry_or_call<0> = apply;
}}
template <std::size_t n, typename F>
struct curry_t {
F f;
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) const& {
static_assert(sizeof...(x) <= n,
"too many arguments provided to boost::hana::curry");
return curry_detail::curry_or_call<n - sizeof...(x)>(
partial(f, static_cast<X&&>(x)...)
);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) & {
static_assert(sizeof...(x) <= n,
"too many arguments provided to boost::hana::curry");
return curry_detail::curry_or_call<n - sizeof...(x)>(
partial(f, static_cast<X&&>(x)...)
);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) && {
static_assert(sizeof...(x) <= n,
"too many arguments provided to boost::hana::curry");
return curry_detail::curry_or_call<n - sizeof...(x)>(
partial(std::move(f), static_cast<X&&>(x)...)
);
}
};
template <typename F>
struct curry_t<0, F> {
F f;
constexpr decltype(auto) operator()() const&
{ return f(); }
constexpr decltype(auto) operator()() &
{ return f(); }
constexpr decltype(auto) operator()() &&
{ return std::move(f)(); }
};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_CURRY_HPP

View File

@ -0,0 +1,269 @@
/*!
@file
Defines `boost::hana::demux`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_DEMUX_HPP
#define BOOST_HANA_FUNCTIONAL_DEMUX_HPP
#include <boost/hana/basic_tuple.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <cstddef>
#include <utility>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Invoke a function with the results of invoking other functions
//! on its arguments.
//!
//! Specifically, `demux(f)(g...)` is a function such that
//! @code
//! demux(f)(g...)(x...) == f(g(x...)...)
//! @endcode
//!
//! Each `g` is called with all the arguments, and then `f` is called
//! with the result of each `g`. Hence, the arity of `f` must match
//! the number of `g`s.
//!
//! This is called `demux` because of a vague similarity between this
//! device and a demultiplexer in signal processing. `demux` takes what
//! can be seen as a continuation (`f`), a bunch of functions to split a
//! signal (`g...`) and zero or more arguments representing the signal
//! (`x...`). Then, it calls the continuation with the result of
//! splitting the signal with whatever functions where given.
//!
//! @note
//! When used with two functions only, `demux` is associative. In other
//! words (and noting `demux(f, g) = demux(f)(g)` to ease the notation),
//! it is true that `demux(demux(f, g), h) == demux(f, demux(g, h))`.
//!
//!
//! Signature
//! ---------
//! The signature of `demux` is
//! \f[
//! \mathtt{demux} :
//! (B_1 \times \dotsb \times B_n \to C)
//! \to ((A_1 \times \dotsb \times A_n \to B_1)
//! \times \dotsb
//! \times (A_1 \times \dotsb \times A_n \to B_n))
//! \to (A_1 \times \dotsb \times A_n \to C)
//! \f]
//!
//! This can be rewritten more tersely as
//! \f[
//! \mathtt{demux} :
//! \left(\prod_{i=1}^n B_i \to C \right)
//! \to \prod_{j=1}^n \left(\prod_{i=1}^n A_i \to B_j \right)
//! \to \left(\prod_{i=1}^n A_i \to C \right)
//! \f]
//!
//!
//! Link with normal composition
//! ----------------------------
//! The signature of `compose` is
//! \f[
//! \mathtt{compose} : (B \to C) \times (A \to B) \to (A \to C)
//! \f]
//!
//! A valid observation is that this coincides exactly with the type
//! of `demux` when used with a single unary function. Actually, both
//! functions are equivalent:
//! @code
//! demux(f)(g)(x) == compose(f, g)(x)
//! @endcode
//!
//! However, let's now consider the curried version of `compose`,
//! `curry<2>(compose)`:
//! \f[
//! \mathtt{curry_2(compose)} : (B \to C) \to ((A \to B) \to (A \to C))
//! \f]
//!
//! For the rest of this explanation, we'll just consider the curried
//! version of `compose` and so we'll use `compose` instead of
//! `curry<2>(compose)` to lighten the notation. With currying, we can
//! now consider `compose` applied to itself:
//! \f[
//! \mathtt{compose(compose, compose)} :
//! (B \to C) \to (A_1 \to A_2 \to B) \to (A_1 \to A_2 \to C)
//! \f]
//!
//! If we uncurry deeply the above expression, we obtain
//! \f[
//! \mathtt{compose(compose, compose)} :
//! (B \to C) \times (A_1 \times A_2 \to B) \to (A_1 \times A_2 \to C)
//! \f]
//!
//! This signature is exactly the same as that of `demux` when given a
//! single binary function, and indeed they are equivalent definitions.
//! We can also generalize this further by considering
//! `compose(compose(compose, compose), compose)`:
//! \f[
//! \mathtt{compose(compose(compose, compose), compose)} :
//! (B \to C) \to (A_1 \to A_2 \to A_3 \to B)
//! \to (A_1 \to A_2 \to A_3 \to C)
//! \f]
//!
//! which uncurries to
//! \f[
//! \mathtt{compose(compose(compose, compose), compose)} :
//! (B \to C) \times (A_1 \times A_2 \times A_3 \to B)
//! \to (A_1 \times A_2 \times A_3 \to C)
//! \f]
//!
//! This signature is exactly the same as that of `demux` when given a
//! single ternary function. Hence, for a single n-ary function `g`,
//! `demux(f)(g)` is equivalent to the n-times composition of `compose`
//! with itself, applied to `g` and `f`:
//! @code
//! demux(f)(g) == fold_left([compose, ..., compose], id, compose)(g, f)
//! // ^^^^^^^^^^^^^^^^^^^^^ n times
//! @endcode
//!
//! More information on this insight can be seen [here][1]. Also, I'm
//! not sure how this insight could be generalized to more than one
//! function `g`, or if that is even possible.
//!
//!
//! Proof of associativity in the binary case
//! -----------------------------------------
//! As explained above, `demux` is associative when it is used with
//! two functions only. Indeed, given functions `f`, `g` and `h` with
//! suitable signatures, we have
//! @code
//! demux(f)(demux(g)(h))(x...) == f(demux(g)(h)(x...))
//! == f(g(h(x...)))
//! @endcode
//!
//! On the other hand, we have
//! @code
//! demux(demux(f)(g))(h)(x...) == demux(f)(g)(h(x...))
//! == f(g(h(x...)))
//! @endcode
//!
//! and hence `demux` is associative in the binary case.
//!
//!
//! Example
//! -------
//! @include example/functional/demux.cpp
//!
//! [1]: http://stackoverflow.com/q/5821089/627587
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto demux = [](auto&& f) {
return [perfect-capture](auto&& ...g) {
return [perfect-capture](auto&& ...x) -> decltype(auto) {
// x... can't be forwarded unless there is a single g
// function, or that could cause double-moves.
return forwarded(f)(forwarded(g)(x...)...);
};
};
};
#else
template <typename F>
struct pre_demux_t;
struct make_pre_demux_t {
struct secret { };
template <typename F>
constexpr pre_demux_t<typename detail::decay<F>::type> operator()(F&& f) const {
return {static_cast<F&&>(f)};
}
};
template <typename Indices, typename F, typename ...G>
struct demux_t;
template <typename F>
struct pre_demux_t {
F f;
template <typename ...G>
constexpr demux_t<std::make_index_sequence<sizeof...(G)>, F,
typename detail::decay<G>::type...>
operator()(G&& ...g) const& {
return {make_pre_demux_t::secret{}, this->f, static_cast<G&&>(g)...};
}
template <typename ...G>
constexpr demux_t<std::make_index_sequence<sizeof...(G)>, F,
typename detail::decay<G>::type...>
operator()(G&& ...g) && {
return {make_pre_demux_t::secret{}, static_cast<F&&>(this->f), static_cast<G&&>(g)...};
}
};
template <std::size_t ...n, typename F, typename ...G>
struct demux_t<std::index_sequence<n...>, F, G...> {
template <typename ...T>
constexpr demux_t(make_pre_demux_t::secret, T&& ...t)
: storage_{static_cast<T&&>(t)...}
{ }
basic_tuple<F, G...> storage_;
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) const& {
return hana::at_c<0>(storage_)(
hana::at_c<n+1>(storage_)(x...)...
);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) & {
return hana::at_c<0>(storage_)(
hana::at_c<n+1>(storage_)(x...)...
);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) && {
return static_cast<F&&>(hana::at_c<0>(storage_))(
static_cast<G&&>(hana::at_c<n+1>(storage_))(x...)...
);
}
};
template <typename F, typename G>
struct demux_t<std::index_sequence<0>, F, G> {
template <typename ...T>
constexpr demux_t(make_pre_demux_t::secret, T&& ...t)
: storage_{static_cast<T&&>(t)...}
{ }
basic_tuple<F, G> storage_;
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) const& {
return hana::at_c<0>(storage_)(
hana::at_c<1>(storage_)(static_cast<X&&>(x)...)
);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) & {
return hana::at_c<0>(storage_)(
hana::at_c<1>(storage_)(static_cast<X&&>(x)...)
);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) && {
return static_cast<F&&>(hana::at_c<0>(storage_))(
static_cast<G&&>(hana::at_c<1>(storage_))(static_cast<X&&>(x)...)
);
}
};
BOOST_HANA_INLINE_VARIABLE constexpr make_pre_demux_t demux{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_DEMUX_HPP

View File

@ -0,0 +1,83 @@
/*!
@file
Defines `boost::hana::fix`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_FIX_HPP
#define BOOST_HANA_FUNCTIONAL_FIX_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/create.hpp>
#include <utility>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Return a function computing the fixed point of a function.
//!
//! `fix` is an implementation of the [Y-combinator][], also called the
//! fixed-point combinator. It encodes the idea of recursion, and in fact
//! any recursive function can be written in terms of it.
//!
//! Specifically, `fix(f)` is a function such that
//! @code
//! fix(f)(x...) == f(fix(f), x...)
//! @endcode
//!
//! This definition allows `f` to use its first argument as a continuation
//! to call itself recursively. Indeed, if `f` calls its first argument
//! with `y...`, it is equivalent to calling `f(fix(f), y...)` per the
//! above equation.
//!
//! Most of the time, it is more convenient and efficient to define
//! recursive functions without using a fixed-point combinator. However,
//! there are some cases where `fix` provides either more flexibility
//! (e.g. the ability to change the callback inside `f`) or makes it
//! possible to write functions that couldn't be defined recursively
//! otherwise.
//!
//! @param f
//! A function called as `f(self, x...)`, where `x...` are the arguments
//! in the `fix(f)(x...)` expression and `self` is `fix(f)`.
//!
//! ### Example
//! @include example/functional/fix.cpp
//!
//! [Y-combinator]: http://en.wikipedia.org/wiki/Fixed-point_combinator
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto fix = [](auto&& f) {
return [perfect-capture](auto&& ...x) -> decltype(auto) {
return forwarded(f)(fix(f), forwarded(x)...);
};
};
#else
template <typename F>
struct fix_t;
BOOST_HANA_INLINE_VARIABLE constexpr detail::create<fix_t> fix{};
template <typename F>
struct fix_t {
F f;
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) const&
{ return f(fix(f), static_cast<X&&>(x)...); }
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) &
{ return f(fix(f), static_cast<X&&>(x)...); }
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) &&
{ return std::move(f)(fix(f), static_cast<X&&>(x)...); }
};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_FIX_HPP

View File

@ -0,0 +1,73 @@
/*!
@file
Defines `boost::hana::flip`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_FLIP_HPP
#define BOOST_HANA_FUNCTIONAL_FLIP_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/create.hpp>
#include <utility>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Invoke a function with its two first arguments reversed.
//!
//! Specifically, `flip(f)` is a function such that
//! @code
//! flip(f)(x, y, z...) == f(y, x, z...)
//! @endcode
//!
//! ### Example
//! @include example/functional/flip.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto flip = [](auto&& f) {
return [perfect-capture](auto&& x, auto&& y, auto&& ...z) -> decltype(auto) {
return forwarded(f)(forwarded(y), forwarded(x), forwarded(z)...);
};
};
#else
template <typename F>
struct flip_t {
F f;
template <typename X, typename Y, typename ...Z>
constexpr decltype(auto) operator()(X&& x, Y&& y, Z&& ...z) const& {
return f(
static_cast<Y&&>(y),
static_cast<X&&>(x),
static_cast<Z&&>(z)...
);
}
template <typename X, typename Y, typename ...Z>
constexpr decltype(auto) operator()(X&& x, Y&& y, Z&& ...z) & {
return f(
static_cast<Y&&>(y),
static_cast<X&&>(x),
static_cast<Z&&>(z)...
);
}
template <typename X, typename Y, typename ...Z>
constexpr decltype(auto) operator()(X&& x, Y&& y, Z&& ...z) && {
return std::move(f)(
static_cast<Y&&>(y),
static_cast<X&&>(x),
static_cast<Z&&>(z)...
);
}
};
BOOST_HANA_INLINE_VARIABLE constexpr detail::create<flip_t> flip{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_FLIP_HPP

View File

@ -0,0 +1,38 @@
/*!
@file
Defines `boost::hana::id`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_ID_HPP
#define BOOST_HANA_FUNCTIONAL_ID_HPP
#include <boost/hana/config.hpp>
namespace boost { namespace hana {
//! @ingroup group-functional
//! The identity function -- returns its argument unchanged.
//!
//! ### Example
//! @include example/functional/id.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto id = [](auto&& x) -> decltype(auto) {
return forwarded(x);
};
#else
struct id_t {
template <typename T>
constexpr T operator()(T&& t) const {
return static_cast<T&&>(t);
}
};
BOOST_HANA_INLINE_VARIABLE constexpr id_t id{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_ID_HPP

View File

@ -0,0 +1,185 @@
/*!
@file
Defines `boost::hana::infix`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_INFIX_HPP
#define BOOST_HANA_FUNCTIONAL_INFIX_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <boost/hana/functional/partial.hpp>
#include <boost/hana/functional/reverse_partial.hpp>
#include <type_traits>
#include <utility>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Return an equivalent function that can also be applied in infix
//! notation.
//!
//! Specifically, `infix(f)` is an object such that:
//! @code
//! infix(f)(x1, ..., xn) == f(x1, ..., xn)
//! x ^infix(f)^ y == f(x, y)
//! @endcode
//!
//! Hence, the returned function can still be applied using the usual
//! function call syntax, but it also gains the ability to be applied in
//! infix notation. The infix syntax allows a great deal of expressiveness,
//! especially when used in combination with some higher order algorithms.
//! Since `operator^` is left-associative, `x ^infix(f)^ y` is actually
//! parsed as `(x ^infix(f))^ y`. However, for flexibility, the order in
//! which both arguments are applied in infix notation does not matter.
//! Hence, it is always the case that
//! @code
//! (x ^ infix(f)) ^ y == x ^ (infix(f) ^ y)
//! @endcode
//!
//! However, note that applying more than one argument in infix
//! notation to the same side of the operator will result in a
//! compile-time assertion:
//! @code
//! (infix(f) ^ x) ^ y; // compile-time assertion
//! y ^ (x ^ infix(f)); // compile-time assertion
//! @endcode
//!
//! Additionally, a function created with `infix` may be partially applied
//! in infix notation. Specifically,
//! @code
//! (x ^ infix(f))(y1, ..., yn) == f(x, y1, ..., yn)
//! (infix(f) ^ y)(x1, ..., xn) == f(x1, ..., xn, y)
//! @endcode
//!
//! @internal
//! ### Rationales
//! 1. The `^` operator was chosen because it is left-associative and
//! has a low enough priority so that most expressions will render
//! the expected behavior.
//! 2. The operator can't be customimzed because that would require more
//! sophistication in the implementation; I want to keep it as simple
//! as possible. There is also an advantage in having a uniform syntax
//! for infix application.
//! @endinternal
//!
//! @param f
//! The function which gains the ability to be applied in infix notation.
//! The function must be at least binary; a compile-time error will be
//! triggered otherwise.
//!
//! ### Example
//! @include example/functional/infix.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto infix = [](auto f) {
return unspecified;
};
#else
namespace infix_detail {
// This needs to be in the same namespace as `operator^` so it can be
// found by ADL.
template <bool left, bool right, typename F>
struct infix_t {
F f;
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) const&
{ return f(static_cast<X&&>(x)...); }
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) &
{ return f(static_cast<X&&>(x)...); }
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) &&
{ return std::move(f)(static_cast<X&&>(x)...); }
};
template <bool left, bool right>
struct make_infix {
template <typename F>
constexpr infix_t<left, right, typename detail::decay<F>::type>
operator()(F&& f) const { return {static_cast<F&&>(f)}; }
};
template <bool left, bool right>
struct Infix;
struct Object;
template <typename T>
struct dispatch { using type = Object; };
template <bool left, bool right, typename F>
struct dispatch<infix_t<left, right, F>> {
using type = Infix<left, right>;
};
template <typename, typename>
struct bind_infix;
// infix(f) ^ y
template <>
struct bind_infix<Infix<false, false>, Object> {
template <typename F, typename Y>
static constexpr decltype(auto) apply(F&& f, Y&& y) {
return make_infix<false, true>{}(
hana::reverse_partial(
static_cast<F&&>(f), static_cast<Y&&>(y)
)
);
}
};
// (x^infix(f)) ^ y
template <>
struct bind_infix<Infix<true, false>, Object> {
template <typename F, typename Y>
static constexpr decltype(auto) apply(F&& f, Y&& y) {
return static_cast<F&&>(f)(static_cast<Y&&>(y));
}
};
// x ^ infix(f)
template <>
struct bind_infix<Object, Infix<false, false>> {
template <typename X, typename F>
static constexpr decltype(auto) apply(X&& x, F&& f) {
return make_infix<true, false>{}(
hana::partial(static_cast<F&&>(f), static_cast<X&&>(x))
);
}
};
// x ^ (infix(f)^y)
template <>
struct bind_infix<Object, Infix<false, true>> {
template <typename X, typename F>
static constexpr decltype(auto) apply(X&& x, F&& f) {
return static_cast<F&&>(f)(static_cast<X&&>(x));
}
};
template <typename T>
using strip = typename std::remove_cv<
typename std::remove_reference<T>::type
>::type;
template <typename X, typename Y>
constexpr decltype(auto) operator^(X&& x, Y&& y) {
return bind_infix<
typename dispatch<strip<X>>::type,
typename dispatch<strip<Y>>::type
>::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
}
} // end namespace infix_detail
BOOST_HANA_INLINE_VARIABLE constexpr infix_detail::make_infix<false, false> infix{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_INFIX_HPP

View File

@ -0,0 +1,201 @@
/*!
@file
Defines `boost::hana::iterate`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_ITERATE_HPP
#define BOOST_HANA_FUNCTIONAL_ITERATE_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
#include <boost/hana/functional/partial.hpp>
#include <cstddef>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Applies another function `n` times to its argument.
//!
//! Given a function `f` and an argument `x`, `iterate<n>(f, x)` returns
//! the result of applying `f` `n` times to its argument. In other words,
//! @code
//! iterate<n>(f, x) == f(f( ... f(x)))
//! ^^^^^^^^^^ n times total
//! @endcode
//!
//! If `n == 0`, `iterate<n>(f, x)` returns the `x` argument unchanged
//! and `f` is never applied. It is important to note that the function
//! passed to `iterate<n>` must be a unary function. Indeed, since `f`
//! will be called with the result of the previous `f` application, it
//! may only take a single argument.
//!
//! In addition to what's documented above, `iterate` can also be
//! partially applied to the function argument out-of-the-box. In
//! other words, `iterate<n>(f)` is a function object applying `f`
//! `n` times to the argument it is called with, which means that
//! @code
//! iterate<n>(f)(x) == iterate<n>(f, x)
//! @endcode
//!
//! This is provided for convenience, and it turns out to be especially
//! useful in conjunction with higher-order algorithms.
//!
//!
//! Signature
//! ---------
//! Given a function \f$ f : T \to T \f$ and `x` and argument of data
//! type `T`, the signature is
//! \f$
//! \mathtt{iterate_n} : (T \to T) \times T \to T
//! \f$
//!
//! @tparam n
//! An unsigned integer representing the number of times that `f`
//! should be applied to its argument.
//!
//! @param f
//! A function to apply `n` times to its argument.
//!
//! @param x
//! The initial value to call `f` with.
//!
//!
//! Example
//! -------
//! @include example/functional/iterate.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
template <std::size_t n>
constexpr auto iterate = [](auto&& f) {
return [perfect-capture](auto&& x) -> decltype(auto) {
return f(f( ... f(forwarded(x))));
};
};
#else
template <std::size_t n, typename = when<true>>
struct iterate_t;
template <>
struct iterate_t<0> {
template <typename F, typename X>
constexpr X operator()(F&&, X&& x) const
{ return static_cast<X&&>(x); }
};
template <>
struct iterate_t<1> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return f(static_cast<X&&>(x));
}
};
template <>
struct iterate_t<2> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return f(f(static_cast<X&&>(x)));
}
};
template <>
struct iterate_t<3> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return f(f(f(static_cast<X&&>(x))));
}
};
template <>
struct iterate_t<4> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return f(f(f(f(static_cast<X&&>(x)))));
}
};
template <>
struct iterate_t<5> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return f(f(f(f(f(static_cast<X&&>(x))))));
}
};
template <std::size_t n>
struct iterate_t<n, when<(n >= 6) && (n < 12)>> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return iterate_t<n - 6>{}(f,
f(f(f(f(f(f(static_cast<X&&>(x)))))))
);
}
};
template <std::size_t n>
struct iterate_t<n, when<(n >= 12) && (n < 24)>> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return iterate_t<n - 12>{}(f,
f(f(f(f(f(f(f(f(f(f(f(f(
static_cast<X&&>(x)
))))))))))))
);
}
};
template <std::size_t n>
struct iterate_t<n, when<(n >= 24) && (n < 48)>> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return iterate_t<n - 24>{}(f,
f(f(f(f(f(f(f(f(f(f(f(f(
f(f(f(f(f(f(f(f(f(f(f(f(
static_cast<X&&>(x)
))))))))))))
))))))))))))
);
}
};
template <std::size_t n>
struct iterate_t<n, when<(n >= 48)>> {
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return iterate_t<n - 48>{}(f,
f(f(f(f(f(f(f(f(f(f(f(f(
f(f(f(f(f(f(f(f(f(f(f(f(
f(f(f(f(f(f(f(f(f(f(f(f(
f(f(f(f(f(f(f(f(f(f(f(f(
static_cast<X&&>(x)
))))))))))))
))))))))))))
))))))))))))
))))))))))))
);
}
};
template <std::size_t n>
struct make_iterate_t {
template <typename F>
constexpr decltype(auto) operator()(F&& f) const
{ return hana::partial(iterate_t<n>{}, static_cast<F&&>(f)); }
template <typename F, typename X>
constexpr decltype(auto) operator()(F&& f, X&& x) const {
return iterate_t<n>{}(static_cast<F&&>(f),
static_cast<X&&>(x));
}
};
template <std::size_t n>
BOOST_HANA_INLINE_VARIABLE constexpr make_iterate_t<n> iterate{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_ITERATE_HPP

View File

@ -0,0 +1,114 @@
/*!
@file
Defines `boost::hana::lockstep`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_LOCKSTEP_HPP
#define BOOST_HANA_FUNCTIONAL_LOCKSTEP_HPP
#include <boost/hana/basic_tuple.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <cstddef>
#include <utility>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Invoke a function with the result of invoking other functions on its
//! arguments, in lockstep.
//!
//! Specifically, `lockstep(f)(g1, ..., gN)` is a function such that
//! @code
//! lockstep(f)(g1, ..., gN)(x1, ..., xN) == f(g1(x1), ..., gN(xN))
//! @endcode
//!
//! Since each `g` is invoked on its corresponding argument in lockstep,
//! the number of arguments must match the number of `g`s.
//!
//!
//! Example
//! -------
//! @include example/functional/lockstep.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto lockstep = [](auto&& f, auto&& ...g) {
return [perfect-capture](auto&& ...x) -> decltype(auto) {
return forwarded(f)(forwarded(g)(forwarded(x))...);
};
};
#else
template <typename Indices, typename F, typename ...G>
struct lockstep_t;
template <typename F>
struct pre_lockstep_t;
struct make_pre_lockstep_t {
struct secret { };
template <typename F>
constexpr pre_lockstep_t<typename detail::decay<F>::type> operator()(F&& f) const {
return {static_cast<F&&>(f)};
}
};
template <std::size_t ...n, typename F, typename ...G>
struct lockstep_t<std::index_sequence<n...>, F, G...> {
template <typename ...T>
constexpr lockstep_t(make_pre_lockstep_t::secret, T&& ...t)
: storage_{static_cast<T&&>(t)...}
{ }
basic_tuple<F, G...> storage_;
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) const& {
return hana::at_c<0>(storage_)(
hana::at_c<n+1>(storage_)(static_cast<X&&>(x))...
);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) & {
return hana::at_c<0>(storage_)(
hana::at_c<n+1>(storage_)(static_cast<X&&>(x))...
);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) && {
return static_cast<F&&>(hana::at_c<0>(storage_))(
static_cast<G&&>(hana::at_c<n+1>(storage_))(static_cast<X&&>(x))...
);
}
};
template <typename F>
struct pre_lockstep_t {
F f;
template <typename ...G>
constexpr lockstep_t<std::make_index_sequence<sizeof...(G)>, F,
typename detail::decay<G>::type...>
operator()(G&& ...g) const& {
return {make_pre_lockstep_t::secret{}, this->f, static_cast<G&&>(g)...};
}
template <typename ...G>
constexpr lockstep_t<std::make_index_sequence<sizeof...(G)>, F,
typename detail::decay<G>::type...>
operator()(G&& ...g) && {
return {make_pre_lockstep_t::secret{}, static_cast<F&&>(this->f),
static_cast<G&&>(g)...};
}
};
BOOST_HANA_INLINE_VARIABLE constexpr make_pre_lockstep_t lockstep{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_LOCKSTEP_HPP

View File

@ -0,0 +1,83 @@
/*!
@file
Defines `boost::hana::on`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_ON_HPP
#define BOOST_HANA_FUNCTIONAL_ON_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/create.hpp>
#include <boost/hana/functional/infix.hpp>
#include <utility>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Invoke a function with the result of invoking another function on
//! each argument.
//!
//! Specifically, `on(f, g)` is a function such that
//! @code
//! on(f, g)(x...) == f(g(x)...)
//! @endcode
//!
//! For convenience, `on` also supports infix application as provided
//! by `infix`.
//!
//!
//! @note
//! `on` is associative, i.e. `on(f, on(g, h))` is equivalent to
//! `on(on(f, g), h)`.
//!
//! @internal
//! ### Proof of associativity
//!
//! @code
//! on(f, on(g, h))(xs...) == f(on(g, h)(xs)...)
//! == f(g(h(xs))...)
//!
//! on(on(f, g), h)(xs...) == on(f, g)(h(xs)...)
//! == f(g(h(xs))...)
//! @endcode
//! @endinternal
//!
//!
//! ### Example
//! @include example/functional/on.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto on = infix([](auto&& f, auto&& g) {
return [perfect-capture](auto&& ...x) -> decltype(auto) {
return forwarded(f)(g(forwarded(x))...);
};
});
#else
template <typename F, typename G>
struct on_t {
F f; G g;
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) const& {
return f(g(static_cast<X&&>(x))...);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) & {
return f(g(static_cast<X&&>(x))...);
}
template <typename ...X>
constexpr decltype(auto) operator()(X&& ...x) && {
return std::move(f)(g(static_cast<X&&>(x))...);
}
};
BOOST_HANA_INLINE_VARIABLE constexpr auto on = infix(detail::create<on_t>{});
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_ON_HPP

View File

@ -0,0 +1,88 @@
/*!
@file
Defines `boost::hana::overload`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_OVERLOAD_HPP
#define BOOST_HANA_FUNCTIONAL_OVERLOAD_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Pick one of several functions to call based on overload resolution.
//!
//! Specifically, `overload(f1, f2, ..., fn)` is a function object such
//! that
//! @code
//! overload(f1, f2, ..., fn)(x...) == fk(x...)
//! @endcode
//!
//! where `fk` is the function of `f1, ..., fn` that would be called if
//! overload resolution was performed amongst that set of functions only.
//! If more than one function `fk` would be picked by overload resolution,
//! then the call is ambiguous.
//!
//! ### Example
//! @include example/functional/overload.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto overload = [](auto&& f1, auto&& f2, ..., auto&& fn) {
return [perfect-capture](auto&& ...x) -> decltype(auto) {
return forwarded(fk)(forwarded(x)...);
};
};
#else
template <typename F, typename ...G>
struct overload_t
: overload_t<F>::type
, overload_t<G...>::type
{
using type = overload_t;
using overload_t<F>::type::operator();
using overload_t<G...>::type::operator();
template <typename F_, typename ...G_>
constexpr explicit overload_t(F_&& f, G_&& ...g)
: overload_t<F>::type(static_cast<F_&&>(f))
, overload_t<G...>::type(static_cast<G_&&>(g)...)
{ }
};
template <typename F>
struct overload_t<F> { using type = F; };
template <typename R, typename ...Args>
struct overload_t<R(*)(Args...)> {
using type = overload_t;
R (*fptr_)(Args...);
explicit constexpr overload_t(R (*fp)(Args...))
: fptr_(fp)
{ }
constexpr R operator()(Args ...args) const
{ return fptr_(static_cast<Args&&>(args)...); }
};
struct make_overload_t {
template <typename ...F,
typename Overload = typename overload_t<
typename detail::decay<F>::type...
>::type
>
constexpr Overload operator()(F&& ...f) const {
return Overload(static_cast<F&&>(f)...);
}
};
BOOST_HANA_INLINE_VARIABLE constexpr make_overload_t overload{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_OVERLOAD_HPP

View File

@ -0,0 +1,110 @@
/*!
@file
Defines `boost::hana::overload_linearly`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_OVERLOAD_LINEARLY_HPP
#define BOOST_HANA_FUNCTIONAL_OVERLOAD_LINEARLY_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <utility>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Call the first function that produces a valid call expression.
//!
//! Given functions `f1, ..., fn`, `overload_linearly(f1, ..., fn)` is
//! a new function that calls the first `fk` producing a valid call
//! expression with the given arguments. Specifically,
//! @code
//! overload_linearly(f1, ..., fn)(args...) == fk(args...)
//! @endcode
//!
//! where `fk` is the _first_ function such that `fk(args...)` is a valid
//! expression.
//!
//!
//! Example
//! -------
//! @include example/functional/overload_linearly.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto overload_linearly = [](auto&& f1, auto&& f2, ..., auto&& fn) {
return [perfect-capture](auto&& ...x) -> decltype(auto) {
return forwarded(fk)(forwarded(x)...);
};
};
#else
template <typename F, typename G>
struct overload_linearly_t {
F f;
G g;
private:
template <typename ...Args, typename =
decltype(std::declval<F const&>()(std::declval<Args>()...))>
constexpr F const& which(int) const& { return f; }
template <typename ...Args, typename =
decltype(std::declval<F&>()(std::declval<Args>()...))>
constexpr F& which(int) & { return f; }
template <typename ...Args, typename =
decltype(std::declval<F&&>()(std::declval<Args>()...))>
constexpr F which(int) && { return static_cast<F&&>(f); }
template <typename ...Args>
constexpr G const& which(long) const& { return g; }
template <typename ...Args>
constexpr G& which(long) & { return g; }
template <typename ...Args>
constexpr G which(long) && { return static_cast<G&&>(g); }
public:
template <typename ...Args>
constexpr decltype(auto) operator()(Args&& ...args) const&
{ return which<Args...>(int{})(static_cast<Args&&>(args)...); }
template <typename ...Args>
constexpr decltype(auto) operator()(Args&& ...args) &
{ return which<Args...>(int{})(static_cast<Args&&>(args)...); }
template <typename ...Args>
constexpr decltype(auto) operator()(Args&& ...args) &&
{ return which<Args...>(int{})(static_cast<Args&&>(args)...); }
};
struct make_overload_linearly_t {
template <typename F, typename G>
constexpr overload_linearly_t<
typename detail::decay<F>::type,
typename detail::decay<G>::type
> operator()(F&& f, G&& g) const {
return {static_cast<F&&>(f), static_cast<G&&>(g)};
}
template <typename F, typename G, typename ...H>
constexpr decltype(auto) operator()(F&& f, G&& g, H&& ...h) const {
return (*this)(static_cast<F&&>(f),
(*this)(static_cast<G&&>(g), static_cast<H&&>(h)...));
}
template <typename F>
constexpr typename detail::decay<F>::type operator()(F&& f) const {
return static_cast<F&&>(f);
}
};
BOOST_HANA_INLINE_VARIABLE constexpr make_overload_linearly_t overload_linearly{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_OVERLOAD_LINEARLY_HPP

View File

@ -0,0 +1,105 @@
/*!
@file
Defines `boost::hana::partial`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_PARTIAL_HPP
#define BOOST_HANA_FUNCTIONAL_PARTIAL_HPP
#include <boost/hana/basic_tuple.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <cstddef>
#include <utility>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Partially apply a function to some arguments.
//!
//! Given a function `f` and some arguments, `partial` returns a new
//! function corresponding to the partially applied function `f`. This
//! allows providing some arguments to a function and letting the rest
//! of the arguments be provided later. Specifically, `partial(f, x...)`
//! is a function such that
//! @code
//! partial(f, x...)(y...) == f(x..., y...)
//! @endcode
//!
//! @note
//! The arity of `f` must match the total number of arguments passed to
//! it, i.e. `sizeof...(x) + sizeof...(y)`.
//!
//!
//! Example
//! -------
//! @include example/functional/partial.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto partial = [](auto&& f, auto&& ...x) {
return [perfect-capture](auto&& ...y) -> decltype(auto) {
return forwarded(f)(forwarded(x)..., forwarded(y)...);
};
};
#else
template <typename Indices, typename F, typename ...X>
struct partial_t;
struct make_partial_t {
struct secret { };
template <typename F, typename ...X>
constexpr partial_t<
std::make_index_sequence<sizeof...(X)>,
typename detail::decay<F>::type,
typename detail::decay<X>::type...
>
operator()(F&& f, X&& ...x) const {
return {secret{}, static_cast<F&&>(f), static_cast<X&&>(x)...};
}
};
template <std::size_t ...n, typename F, typename ...X>
struct partial_t<std::index_sequence<n...>, F, X...> {
partial_t() = default;
template <typename ...T>
constexpr partial_t(make_partial_t::secret, T&& ...t)
: storage_{static_cast<T&&>(t)...}
{ }
basic_tuple<F, X...> storage_;
template <typename ...Y>
constexpr decltype(auto) operator()(Y&& ...y) const& {
return hana::at_c<0>(storage_)(
hana::at_c<n+1>(storage_)...,
static_cast<Y&&>(y)...
);
}
template <typename ...Y>
constexpr decltype(auto) operator()(Y&& ...y) & {
return hana::at_c<0>(storage_)(
hana::at_c<n+1>(storage_)...,
static_cast<Y&&>(y)...
);
}
template <typename ...Y>
constexpr decltype(auto) operator()(Y&& ...y) && {
return static_cast<F&&>(hana::at_c<0>(storage_))(
static_cast<X&&>(hana::at_c<n+1>(storage_))...,
static_cast<Y&&>(y)...
);
}
};
BOOST_HANA_INLINE_VARIABLE constexpr make_partial_t partial{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_PARTIAL_HPP

View File

@ -0,0 +1,263 @@
/*!
@file
Defines `boost::hana::_`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_PLACEHOLDER_HPP
#define BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP
#include <boost/hana/basic_tuple.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/create.hpp>
#include <boost/hana/detail/decay.hpp>
#include <cstddef>
#include <utility>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Create simple functions representing C++ operators inline.
//!
//! Specifically, `_` is an object used as a placeholder to build
//! function objects representing calls to C++ operators. It works
//! by overloading the operators between `_` and any object so that
//! they return a function object which actually calls the corresponding
//! operator on its argument(s). Hence, for any supported operator `@`:
//! @code
//! (_ @ _)(x, y) == x @ y
//! @endcode
//!
//! Operators may also be partially applied to one argument inline:
//! @code
//! (x @ _)(y) == x @ y
//! (_ @ y)(x) == x @ y
//! @endcode
//!
//! When invoked with more arguments than required, functions created with
//! `_` will discard the superfluous instead of triggering an error:
//! @code
//! (_ @ _)(x, y, z...) == x @ y
//! @endcode
//!
//! This makes functions created with `_` easier to use in higher-order
//! algorithms, which sometime provide more information than necessary
//! to their callbacks.
//!
//! ### Supported operators
//! - Arithmetic: binary `+`, binary `-`, `/`, `*`, `%`, unary `+`, unary `-`
//! - Bitwise: `~`, `&`, `|`, `^`, `<<`, `>>`
//! - Comparison: `==`, `!=`, `<`, `<=`, `>`, `>=`
//! - %Logical: `||`, `&&`, `!`
//! - Member access: `*` (dereference), `[]` (array subscript)
//! - Other: `()` (function call)
//!
//! More complex functionality like the ability to compose placeholders
//! into larger function objects inline are not supported. This is on
//! purpose; you should either use C++14 generic lambdas or a library
//! like [Boost.Phoenix][] if you need bigger guns. The goal here is
//! to save you a couple of characters in simple situations.
//!
//! ### Example
//! @include example/functional/placeholder.cpp
//!
//! [Boost.Phoenix]: http://www.boost.org/doc/libs/release/libs/phoenix/doc/html/index.html
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr unspecified _{};
#else
namespace placeholder_detail {
template <typename I>
struct subscript {
I i;
template <typename Xs, typename ...Z>
constexpr auto operator()(Xs&& xs, Z const& ...) const&
-> decltype(static_cast<Xs&&>(xs)[i])
{ return static_cast<Xs&&>(xs)[i]; }
template <typename Xs, typename ...Z>
constexpr auto operator()(Xs&& xs, Z const& ...) &
-> decltype(static_cast<Xs&&>(xs)[i])
{ return static_cast<Xs&&>(xs)[i]; }
template <typename Xs, typename ...Z>
constexpr auto operator()(Xs&& xs, Z const& ...) &&
-> decltype(static_cast<Xs&&>(xs)[std::declval<I>()])
{ return static_cast<Xs&&>(xs)[std::move(i)]; }
};
template <typename F, typename Xs, std::size_t ...i>
constexpr decltype(auto) invoke_impl(F&& f, Xs&& xs, std::index_sequence<i...>) {
return static_cast<F&&>(f)(hana::at_c<i>(static_cast<Xs&&>(xs).storage_)...);
}
template <typename ...X>
struct invoke;
struct placeholder {
struct secret { };
template <typename X>
constexpr decltype(auto) operator[](X&& x) const
{ return detail::create<subscript>{}(static_cast<X&&>(x)); }
template <typename ...X>
constexpr invoke<typename detail::decay<X>::type...>
operator()(X&& ...x) const {
return {secret{}, static_cast<X&&>(x)...};
}
};
template <typename ...X>
struct invoke {
template <typename ...Y>
constexpr invoke(placeholder::secret, Y&& ...y)
: storage_{static_cast<Y&&>(y)...}
{ }
basic_tuple<X...> storage_;
template <typename F, typename ...Z>
constexpr auto operator()(F&& f, Z const& ...) const& -> decltype(
static_cast<F&&>(f)(std::declval<X const&>()...)
) {
return invoke_impl(static_cast<F&&>(f), *this,
std::make_index_sequence<sizeof...(X)>{});
}
template <typename F, typename ...Z>
constexpr auto operator()(F&& f, Z const& ...) & -> decltype(
static_cast<F&&>(f)(std::declval<X&>()...)
) {
return invoke_impl(static_cast<F&&>(f), *this,
std::make_index_sequence<sizeof...(X)>{});
}
template <typename F, typename ...Z>
constexpr auto operator()(F&& f, Z const& ...) && -> decltype(
static_cast<F&&>(f)(std::declval<X&&>()...)
) {
return invoke_impl(static_cast<F&&>(f), static_cast<invoke&&>(*this),
std::make_index_sequence<sizeof...(X)>{});
}
};
#define BOOST_HANA_PLACEHOLDER_BINARY_OP(op, op_name) \
template <typename X> \
struct op_name ## _left { \
X x; \
\
template <typename Y, typename ...Z> \
constexpr auto operator()(Y&& y, Z const& ...) const& -> decltype( \
std::declval<X const&>() op static_cast<Y&&>(y)) \
{ return x op static_cast<Y&&>(y); } \
\
template <typename Y, typename ...Z> \
constexpr auto operator()(Y&& y, Z const& ...) & -> decltype( \
std::declval<X&>() op static_cast<Y&&>(y)) \
{ return x op static_cast<Y&&>(y); } \
\
template <typename Y, typename ...Z> \
constexpr auto operator()(Y&& y, Z const& ...) && -> decltype( \
std::declval<X>() op static_cast<Y&&>(y)) \
{ return std::move(x) op static_cast<Y&&>(y); } \
}; \
\
template <typename Y> \
struct op_name ## _right { \
Y y; \
\
template <typename X, typename ...Z> \
constexpr auto operator()(X&& x, Z const& ...) const& -> decltype( \
static_cast<X&&>(x) op std::declval<Y const&>()) \
{ return static_cast<X&&>(x) op y; } \
\
template <typename X, typename ...Z> \
constexpr auto operator()(X&& x, Z const& ...) & -> decltype( \
static_cast<X&&>(x) op std::declval<Y&>()) \
{ return static_cast<X&&>(x) op y; } \
\
template <typename X, typename ...Z> \
constexpr auto operator()(X&& x, Z const& ...) && -> decltype( \
static_cast<X&&>(x) op std::declval<Y>()) \
{ return static_cast<X&&>(x) op std::move(y); } \
}; \
\
struct op_name { \
template <typename X, typename Y, typename ...Z> \
constexpr auto operator()(X&& x, Y&& y, Z const& ...) const -> decltype(\
static_cast<X&&>(x) op static_cast<Y&&>(y)) \
{ return static_cast<X&&>(x) op static_cast<Y&&>(y); } \
}; \
\
template <typename X> \
constexpr decltype(auto) operator op (X&& x, placeholder) \
{ return detail::create<op_name ## _left>{}(static_cast<X&&>(x)); } \
\
template <typename Y> \
constexpr decltype(auto) operator op (placeholder, Y&& y) \
{ return detail::create<op_name ## _right>{}(static_cast<Y&&>(y)); } \
\
inline constexpr decltype(auto) operator op (placeholder, placeholder) \
{ return op_name{}; } \
/**/
#define BOOST_HANA_PLACEHOLDER_UNARY_OP(op, op_name) \
struct op_name { \
template <typename X, typename ...Z> \
constexpr auto operator()(X&& x, Z const& ...) const \
-> decltype(op static_cast<X&&>(x)) \
{ return op static_cast<X&&>(x); } \
}; \
\
inline constexpr decltype(auto) operator op (placeholder) \
{ return op_name{}; } \
/**/
// Arithmetic
BOOST_HANA_PLACEHOLDER_UNARY_OP(+, unary_plus)
BOOST_HANA_PLACEHOLDER_UNARY_OP(-, unary_minus)
BOOST_HANA_PLACEHOLDER_BINARY_OP(+, plus)
BOOST_HANA_PLACEHOLDER_BINARY_OP(-, minus)
BOOST_HANA_PLACEHOLDER_BINARY_OP(*, times)
BOOST_HANA_PLACEHOLDER_BINARY_OP(/, divide)
BOOST_HANA_PLACEHOLDER_BINARY_OP(%, modulo)
// Bitwise
BOOST_HANA_PLACEHOLDER_UNARY_OP(~, bitwise_not)
BOOST_HANA_PLACEHOLDER_BINARY_OP(&, bitwise_and)
BOOST_HANA_PLACEHOLDER_BINARY_OP(|, bitwise_or)
BOOST_HANA_PLACEHOLDER_BINARY_OP(^, bitwise_xor)
BOOST_HANA_PLACEHOLDER_BINARY_OP(<<, left_shift)
BOOST_HANA_PLACEHOLDER_BINARY_OP(>>, right_shift)
// Comparison
BOOST_HANA_PLACEHOLDER_BINARY_OP(==, equal)
BOOST_HANA_PLACEHOLDER_BINARY_OP(!=, not_equal)
BOOST_HANA_PLACEHOLDER_BINARY_OP(<, less)
BOOST_HANA_PLACEHOLDER_BINARY_OP(<=, less_equal)
BOOST_HANA_PLACEHOLDER_BINARY_OP(>, greater)
BOOST_HANA_PLACEHOLDER_BINARY_OP(>=, greater_equal)
// Logical
BOOST_HANA_PLACEHOLDER_BINARY_OP(||, logical_or)
BOOST_HANA_PLACEHOLDER_BINARY_OP(&&, logical_and)
BOOST_HANA_PLACEHOLDER_UNARY_OP(!, logical_not)
// Member access (array subscript is a member function)
BOOST_HANA_PLACEHOLDER_UNARY_OP(*, dereference)
// Other (function call is a member function)
#undef BOOST_HANA_PREFIX_PLACEHOLDER_OP
#undef BOOST_HANA_BINARY_PLACEHOLDER_OP
} // end namespace placeholder_detail
BOOST_HANA_INLINE_VARIABLE constexpr placeholder_detail::placeholder _{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP

View File

@ -0,0 +1,103 @@
/*!
@file
Defines `boost::hana::reverse_partial`.
Copyright Louis Dionne 2013-2022
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_FUNCTIONAL_REVERSE_PARTIAL_HPP
#define BOOST_HANA_FUNCTIONAL_REVERSE_PARTIAL_HPP
#include <boost/hana/basic_tuple.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <cstddef>
#include <utility>
namespace boost { namespace hana {
//! @ingroup group-functional
//! Partially apply a function to some arguments.
//!
//! Given a function `f` and some arguments, `reverse_partial` returns a
//! new function corresponding to `f` whose last arguments are partially
//! applied. Specifically, `reverse_partial(f, x...)` is a function such
//! that
//! @code
//! reverse_partial(f, x...)(y...) == f(y..., x...)
//! @endcode
//!
//! @note
//! The arity of `f` must match the total number of arguments passed to
//! it, i.e. `sizeof...(x) + sizeof...(y)`.
//!
//!
//! Example
//! -------
//! @include example/functional/reverse_partial.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto reverse_partial = [](auto&& f, auto&& ...x) {
return [perfect-capture](auto&& ...y) -> decltype(auto) {
return forwarded(f)(forwarded(y)..., forwarded(x)...);
};
};
#else
template <typename Indices, typename F, typename ...X>
struct reverse_partial_t;
struct make_reverse_partial_t {
struct secret { };
template <typename F, typename ...X>
constexpr reverse_partial_t<
std::make_index_sequence<sizeof...(X)>,
typename detail::decay<F>::type,
typename detail::decay<X>::type...
> operator()(F&& f, X&& ...x) const {
return {secret{}, static_cast<F&&>(f), static_cast<X&&>(x)...};
}
};
template <std::size_t ...n, typename F, typename ...X>
struct reverse_partial_t<std::index_sequence<n...>, F, X...> {
reverse_partial_t() = default;
template <typename ...T>
constexpr reverse_partial_t(make_reverse_partial_t::secret, T&& ...t)
: storage_{static_cast<T&&>(t)...}
{ }
basic_tuple<F, X...> storage_;
template <typename ...Y>
constexpr decltype(auto) operator()(Y&& ...y) const& {
return hana::at_c<0>(storage_)(
static_cast<Y&&>(y)...,
hana::at_c<n+1>(storage_)...
);
}
template <typename ...Y>
constexpr decltype(auto) operator()(Y&& ...y) & {
return hana::at_c<0>(storage_)(
static_cast<Y&&>(y)...,
hana::at_c<n+1>(storage_)...
);
}
template <typename ...Y>
constexpr decltype(auto) operator()(Y&& ...y) && {
return static_cast<F&&>(hana::at_c<0>(storage_))(
static_cast<Y&&>(y)...,
static_cast<X&&>(hana::at_c<n+1>(storage_))...
);
}
};
BOOST_HANA_INLINE_VARIABLE constexpr make_reverse_partial_t reverse_partial{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUNCTIONAL_REVERSE_PARTIAL_HPP

View File

@ -0,0 +1,47 @@
/*!
@file
Defines `boost::hana::fuse`.
Copyright Louis Dionne 2013-2022
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_FUSE_HPP
#define BOOST_HANA_FUSE_HPP
#include <boost/hana/fwd/fuse.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/detail/decay.hpp>
#include <boost/hana/unpack.hpp>
namespace boost { namespace hana {
namespace detail {
template <typename F>
struct fused {
F f;
template <typename Xs>
constexpr decltype(auto) operator()(Xs&& xs) const&
{ return hana::unpack(static_cast<Xs&&>(xs), f); }
template <typename Xs>
constexpr decltype(auto) operator()(Xs&& xs) &
{ return hana::unpack(static_cast<Xs&&>(xs), f); }
template <typename Xs>
constexpr decltype(auto) operator()(Xs&& xs) &&
{ return hana::unpack(static_cast<Xs&&>(xs), static_cast<F&&>(f)); }
};
}
//! @cond
template <typename F>
constexpr auto fuse_t::operator()(F&& f) const {
return detail::fused<typename detail::decay<F>::type>{static_cast<F&&>(f)};
}
//! @endcond
}} // end namespace boost::hana
#endif // !BOOST_HANA_FUSE_HPP

View File

@ -0,0 +1,50 @@
/*!
@file
Forward declares `boost::hana::accessors`.
Copyright Louis Dionne 2013-2022
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_FWD_ACCESSORS_HPP
#define BOOST_HANA_FWD_ACCESSORS_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
namespace boost { namespace hana {
//! Returns a `Sequence` of pairs representing the accessors of the
//! data structure.
//! @ingroup group-Struct
//!
//! Given a `Struct` `S`, `accessors<S>()` is a `Sequence` of `Product`s
//! where the first element of each pair is the "name" of a member of
//! the `Struct`, and the second element of each pair is a function that
//! can be used to access that member when given an object of the proper
//! data type. As described in the global documentation for `Struct`, the
//! accessor functions in this sequence must be move-independent.
//!
//!
//! Example
//! -------
//! @include example/accessors.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
template <typename S>
constexpr auto accessors = []() {
return tag-dispatched;
};
#else
template <typename S, typename = void>
struct accessors_impl : accessors_impl<S, when<true>> { };
template <typename S>
struct accessors_t;
template <typename S>
BOOST_HANA_INLINE_VARIABLE constexpr accessors_t<S> accessors{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FWD_ACCESSORS_HPP

View File

@ -0,0 +1,48 @@
/*!
@file
Documents the `BOOST_HANA_ADAPT_ADT` macro.
Copyright Louis Dionne 2013-2022
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_FWD_ADAPT_ADT_HPP
#define BOOST_HANA_FWD_ADAPT_ADT_HPP
#include <boost/hana/config.hpp>
namespace boost { namespace hana {
// Note:
// The weird definition as a variable seems to exploit a glitch in Doxygen
// which makes the macro appear in the related objects of Struct (as we
// want it to).
//! Defines a model of `Struct` with the given accessors.
//! @ingroup group-Struct
//!
//! Using this macro at _global scope_ will define a model of the `Struct`
//! concept for the given type. This can be used to easily adapt existing
//! user-defined types in a ad-hoc manner. Unlike `BOOST_HANA_ADAPT_STRUCT`,
//! this macro requires specifying the way to retrieve each member by
//! providing a function that does the extraction.
//!
//! @note
//! This macro only works if the tag of the user-defined type `T` is `T`
//! itself. This is the case unless you specifically asked for something
//! different; see `tag_of`'s documentation.
//!
//!
//! Example
//! -------
//! @include example/adapt_adt.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
auto BOOST_HANA_ADAPT_ADT(...) = ;
#define BOOST_HANA_ADAPT_ADT(Name, ...) see documentation
#else
// defined in <boost/hana/adapt_adt.hpp>
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FWD_ADAPT_ADT_HPP

View File

@ -0,0 +1,48 @@
/*!
@file
Documents the `BOOST_HANA_ADAPT_STRUCT` macro.
Copyright Louis Dionne 2013-2022
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_FWD_ADAPT_STRUCT_HPP
#define BOOST_HANA_FWD_ADAPT_STRUCT_HPP
#include <boost/hana/config.hpp>
namespace boost { namespace hana {
// Note:
// The weird definition as a variable seems to exploit a glitch in Doxygen
// which makes the macro appear in the related objects of Struct (as we
// want it to).
//! Defines a model of `Struct` with the given members.
//! @ingroup group-Struct
//!
//! Using this macro at _global scope_ will define a model of the `Struct`
//! concept for the given type. This can be used to easily adapt existing
//! user-defined types in a ad-hoc manner. Unlike the
//! `BOOST_HANA_DEFINE_STRUCT` macro, this macro does not
//! require the types of the members to be specified.
//!
//! @note
//! This macro only works if the tag of the user-defined type `T` is `T`
//! itself. This is the case unless you specifically asked for something
//! different; see `tag_of`'s documentation.
//!
//!
//! Example
//! -------
//! @include example/adapt_struct.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
auto BOOST_HANA_ADAPT_STRUCT(...) = ;
#define BOOST_HANA_ADAPT_STRUCT(Name, ...) see documentation
#else
// defined in <boost/hana/adapt_struct.hpp>
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FWD_ADAPT_STRUCT_HPP

View File

@ -0,0 +1,64 @@
/*!
@file
Forward declares `boost::hana::adjust`.
Copyright Louis Dionne 2013-2022
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_FWD_ADJUST_HPP
#define BOOST_HANA_FWD_ADJUST_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
namespace boost { namespace hana {
//! Apply a function on all the elements of a structure that compare
//! equal to some value.
//! @ingroup group-Functor
//!
//!
//! Signature
//! ---------
//! Given `F` a Functor and `U` a type that can be compared with `T`'s,
//! the signature is
//! \f$
//! \mathtt{adjust} : F(T) \times U \times (T \to T) \to F(T)
//! \f$
//!
//! @param xs
//! The structure to adjust with `f`.
//!
//! @param value
//! An object that is compared with each element `x` of the structure.
//! Elements of the structure that compare equal to `value` are adjusted
//! with the `f` function.
//!
//! @param f
//! A function called as `f(x)` on the element(s) of the structure that
//! compare equal to `value`.
//!
//!
//! Example
//! -------
//! @include example/adjust.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto adjust = [](auto&& xs, auto&& value, auto&& f) {
return tag-dispatched;
};
#else
template <typename Xs, typename = void>
struct adjust_impl : adjust_impl<Xs, when<true>> { };
struct adjust_t {
template <typename Xs, typename Value, typename F>
constexpr auto operator()(Xs&& xs, Value&& value, F&& f) const;
};
BOOST_HANA_INLINE_VARIABLE constexpr adjust_t adjust{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FWD_ADJUST_HPP

View File

@ -0,0 +1,69 @@
/*!
@file
Forward declares `boost::hana::adjust_if`.
Copyright Louis Dionne 2013-2022
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_FWD_ADJUST_IF_HPP
#define BOOST_HANA_FWD_ADJUST_IF_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
namespace boost { namespace hana {
//! Apply a function on all the elements of a structure satisfying a predicate.
//! @ingroup group-Functor
//!
//! Given a Functor, a predicate `pred` and a function `f`, `adjust_if`
//! will _adjust_ the elements of the Functor that satisfy the predicate
//! with the function `f`. In other words, `adjust_if` will return a new
//! Functor equal to the original one, except that the elements satisfying
//! the predicate will be transformed with the given function. Elements
//! for which the predicate is not satisfied are left untouched, and they
//! are kept as-is in the resulting Functor.
//!
//!
//! Signature
//! ---------
//! Given a `Functor` `F` and a `Logical` `Bool`, the signature is
//! \f$
//! \mathtt{adjust\_if} : F(T) \times (T \to Bool) \times (T \to T) \to F(T)
//! \f$
//!
//! @param xs
//! The structure to adjust with `f`.
//!
//! @param pred
//! A function called as `pred(x)` for each element of the Functor,
//! and returning whether `f` should be applied on that element.
//!
//! @param f
//! A function called as `f(x)` on the element(s) of the Functor that
//! satisfy the predicate.
//!
//!
//! Example
//! -------
//! @include example/adjust_if.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto adjust_if = [](auto&& xs, auto const& pred, auto const& f) {
return tag-dispatched;
};
#else
template <typename Xs, typename = void>
struct adjust_if_impl : adjust_if_impl<Xs, when<true>> { };
struct adjust_if_t {
template <typename Xs, typename Pred, typename F>
constexpr auto operator()(Xs&& xs, Pred const& pred, F const& f) const;
};
BOOST_HANA_INLINE_VARIABLE constexpr adjust_if_t adjust_if{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FWD_ADJUST_IF_HPP

View File

@ -0,0 +1,46 @@
/*!
@file
Forward declares `boost::hana::all`.
Copyright Louis Dionne 2013-2022
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_FWD_ALL_HPP
#define BOOST_HANA_FWD_ALL_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
namespace boost { namespace hana {
//! Returns whether all the keys of the structure are true-valued.
//! @ingroup group-Searchable
//!
//! The keys of the structure must be `Logical`s. If the structure is not
//! finite, a false-valued key must appear at a finite "index" in order
//! for this method to finish.
//!
//!
//! Example
//! -------
//! @include example/all.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto all = [](auto&& xs) {
return tag-dispatched;
};
#else
template <typename S, typename = void>
struct all_impl : all_impl<S, when<true>> { };
struct all_t {
template <typename Xs>
constexpr auto operator()(Xs&& xs) const;
};
BOOST_HANA_INLINE_VARIABLE constexpr all_t all{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FWD_ALL_HPP

View File

@ -0,0 +1,54 @@
/*!
@file
Forward declares `boost::hana::all_of`.
Copyright Louis Dionne 2013-2022
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_FWD_ALL_OF_HPP
#define BOOST_HANA_FWD_ALL_OF_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
namespace boost { namespace hana {
//! Returns whether all the keys of the structure satisfy the `predicate`.
//! @ingroup group-Searchable
//!
//! If the structure is not finite, `predicate` has to return a false-
//! valued `Logical` after looking at a finite number of keys for this
//! method to finish.
//!
//!
//! @param xs
//! The structure to search.
//!
//! @param predicate
//! A function called as `predicate(k)`, where `k` is a key of the
//! structure, and returning a `Logical`.
//!
//!
//! Example
//! -------
//! @include example/all_of.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto all_of = [](auto&& xs, auto&& predicate) {
return tag-dispatched;
};
#else
template <typename S, typename = void>
struct all_of_impl : all_of_impl<S, when<true>> { };
struct all_of_t {
template <typename Xs, typename Pred>
constexpr auto operator()(Xs&& xs, Pred&& pred) const;
};
BOOST_HANA_INLINE_VARIABLE constexpr all_of_t all_of{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FWD_ALL_OF_HPP

View File

@ -0,0 +1,53 @@
/*!
@file
Forward declares `boost::hana::and_`.
Copyright Louis Dionne 2013-2022
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_FWD_AND_HPP
#define BOOST_HANA_FWD_AND_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
namespace boost { namespace hana {
//! Return whether all the arguments are true-valued.
//! @ingroup group-Logical
//!
//! `and_` can be called with one argument or more. When called with
//! two arguments, `and_` uses tag-dispatching to find the right
//! implementation. Otherwise,
//! @code
//! and_(x) == x
//! and_(x, y, ...z) == and_(and_(x, y), z...)
//! @endcode
//!
//!
//! Example
//! -------
//! @include example/and.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto and_ = [](auto&& x, auto&& ...y) -> decltype(auto) {
return tag-dispatched;
};
#else
template <typename L, typename = void>
struct and_impl : and_impl<L, when<true>> { };
struct and_t {
template <typename X, typename Y>
constexpr decltype(auto) operator()(X&& x, Y&& y) const;
template <typename X, typename ...Y>
constexpr decltype(auto) operator()(X&& x, Y&& ...y) const;
};
BOOST_HANA_INLINE_VARIABLE constexpr and_t and_{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FWD_AND_HPP

View File

@ -0,0 +1,46 @@
/*!
@file
Forward declares `boost::hana::any`.
Copyright Louis Dionne 2013-2022
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_FWD_ANY_HPP
#define BOOST_HANA_FWD_ANY_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
namespace boost { namespace hana {
//! Returns whether any key of the structure is true-valued.
//! @ingroup group-Searchable
//!
//! The keys of the structure must be `Logical`s. If the structure is not
//! finite, a true-valued key must appear at a finite "index" in order for
//! this method to finish.
//!
//!
//! Example
//! -------
//! @include example/any.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto any = [](auto&& xs) {
return tag-dispatched;
};
#else
template <typename S, typename = void>
struct any_impl : any_impl<S, when<true>> { };
struct any_t {
template <typename Xs>
constexpr auto operator()(Xs&& xs) const;
};
BOOST_HANA_INLINE_VARIABLE constexpr any_t any{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FWD_ANY_HPP

View File

@ -0,0 +1,53 @@
/*!
@file
Forward declares `boost::hana::any_of`.
Copyright Louis Dionne 2013-2022
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_FWD_ANY_OF_HPP
#define BOOST_HANA_FWD_ANY_OF_HPP
#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>
namespace boost { namespace hana {
//! Returns whether any key of the structure satisfies the `predicate`.
//! @ingroup group-Searchable
//!
//! If the structure is not finite, `predicate` has to be satisfied
//! after looking at a finite number of keys for this method to finish.
//!
//!
//! @param xs
//! The structure to search.
//!
//! @param predicate
//! A function called as `predicate(k)`, where `k` is a key of the
//! structure, and returning a `Logical`.
//!
//!
//! Example
//! -------
//! @include example/any_of.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
constexpr auto any_of = [](auto&& xs, auto&& predicate) {
return tag-dispatched;
};
#else
template <typename S, typename = void>
struct any_of_impl : any_of_impl<S, when<true>> { };
struct any_of_t {
template <typename Xs, typename Pred>
constexpr auto operator()(Xs&& xs, Pred&& pred) const;
};
BOOST_HANA_INLINE_VARIABLE constexpr any_of_t any_of{};
#endif
}} // end namespace boost::hana
#endif // !BOOST_HANA_FWD_ANY_OF_HPP

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