mirror of
https://github.com/boostorg/hof.git
synced 2026-02-01 08:32:12 +00:00
Merge branch 'is_unpackable'
This commit is contained in:
@@ -40,6 +40,23 @@ Example
|
||||
assert(r == 5);
|
||||
|
||||
|
||||
is_unpackable
|
||||
=============
|
||||
|
||||
This is a trait that can be used to detect whethet the type can be called
|
||||
with `unpack`.
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
template<class T>
|
||||
struct is_unpackable;
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
static_assert(fit::is_unpackable<std::tuple<int>>::value, "Failed");
|
||||
|
||||
unpack_sequence
|
||||
===============
|
||||
|
||||
|
||||
23
fit/detail/and.h
Normal file
23
fit/detail/and.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2015 Paul Fultz II
|
||||
and.h
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef FIT_GUARD_AND_H
|
||||
#define FIT_GUARD_AND_H
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace fit { namespace detail {
|
||||
|
||||
template<bool...> struct bool_seq {};
|
||||
template<class... Ts>
|
||||
struct and_
|
||||
: std::is_same<bool_seq<Ts::value...>, bool_seq<(Ts::value, true)...>>::type
|
||||
{};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <fit/detail/and.h>
|
||||
#include <fit/detail/holder.h>
|
||||
#include <fit/detail/forward.h>
|
||||
|
||||
@@ -63,12 +64,6 @@ struct enable_if_constructible
|
||||
// static_assert(!std::is_same<X, fit::detail::pack_base<fit::detail::seq<0>, std::unique_ptr<int> > >::value, "");
|
||||
};
|
||||
|
||||
template<bool...> struct bool_seq {};
|
||||
template<class... Ts>
|
||||
struct and_
|
||||
: std::is_same<bool_seq<Ts::value...>, bool_seq<(Ts::value, true)...>>::type
|
||||
{};
|
||||
|
||||
template<class T, class=void>
|
||||
struct is_default_constructible_helper
|
||||
: std::false_type
|
||||
|
||||
95
fit/unpack.h
95
fit/unpack.h
@@ -50,6 +50,23 @@
|
||||
/// assert(r == 5);
|
||||
///
|
||||
///
|
||||
/// is_unpackable
|
||||
/// =============
|
||||
///
|
||||
/// This is a trait that can be used to detect whethet the type can be called
|
||||
/// with `unpack`.
|
||||
///
|
||||
/// Synopsis
|
||||
/// --------
|
||||
///
|
||||
/// template<class T>
|
||||
/// struct is_unpackable;
|
||||
///
|
||||
/// Example
|
||||
/// -------
|
||||
///
|
||||
/// static_assert(fit::is_unpackable<std::tuple<int>>::value, "Failed");
|
||||
///
|
||||
/// unpack_sequence
|
||||
/// ===============
|
||||
///
|
||||
@@ -81,7 +98,10 @@
|
||||
#include <fit/detail/seq.h>
|
||||
#include <fit/capture.h>
|
||||
#include <fit/always.h>
|
||||
#include <fit/reveal.h>
|
||||
#include <fit/detail/and.h>
|
||||
#include <fit/detail/delegate.h>
|
||||
#include <fit/detail/holder.h>
|
||||
#include <fit/detail/move.h>
|
||||
#include <fit/detail/make.h>
|
||||
#include <fit/detail/static_constexpr.h>
|
||||
@@ -89,9 +109,24 @@
|
||||
namespace fit {
|
||||
|
||||
template<class Sequence, class=void>
|
||||
struct unpack_sequence;
|
||||
struct unpack_sequence
|
||||
{
|
||||
typedef void not_unpackable;
|
||||
};
|
||||
|
||||
|
||||
namespace detail {
|
||||
template<class Sequence, class=void>
|
||||
struct is_unpackable_impl
|
||||
: std::true_type
|
||||
{};
|
||||
|
||||
template<class Sequence>
|
||||
struct is_unpackable_impl<Sequence, typename detail::holder<
|
||||
typename unpack_sequence<Sequence>::not_unpackable
|
||||
>::type>
|
||||
: std::false_type
|
||||
{};
|
||||
|
||||
template<class F, class Sequence>
|
||||
constexpr auto unpack_impl(F&& f, Sequence&& s) FIT_RETURNS
|
||||
@@ -108,6 +143,13 @@ constexpr auto unpack_join(F&& f, Sequences&&... s) FIT_RETURNS
|
||||
|
||||
}
|
||||
|
||||
template<class Sequence>
|
||||
struct is_unpackable
|
||||
: detail::is_unpackable_impl<
|
||||
typename std::remove_cv<typename std::remove_reference<Sequence>::type>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template<class F>
|
||||
struct unpack_adaptor : F
|
||||
{
|
||||
@@ -119,16 +161,63 @@ struct unpack_adaptor : F
|
||||
return always_ref(*this)(xs...);
|
||||
}
|
||||
|
||||
struct unpack_failure
|
||||
{
|
||||
template<class Failure>
|
||||
struct apply
|
||||
{
|
||||
struct deducer
|
||||
{
|
||||
template<class... Ts>
|
||||
typename Failure::template of<Ts...> operator()(Ts&&...) const;
|
||||
};
|
||||
|
||||
template<class T, class=typename std::enable_if<(
|
||||
is_unpackable<T>::value
|
||||
)>::type>
|
||||
static auto deduce(T&& x)
|
||||
FIT_RETURNS
|
||||
(
|
||||
detail::unpack_impl(deducer(), fit::forward<T>(x))
|
||||
);
|
||||
|
||||
template<class T, class... Ts, class=typename std::enable_if<(detail::and_<
|
||||
is_unpackable<T>, is_unpackable<Ts>...
|
||||
>::value)>::type>
|
||||
static auto deduce(T&& x, Ts&&... xs) FIT_RETURNS
|
||||
(
|
||||
detail::unpack_join(deducer(), fit::forward<T>(x), fit::forward<Ts>(xs)...)
|
||||
);
|
||||
|
||||
template<class... Ts>
|
||||
struct of
|
||||
#if defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7
|
||||
: std::enable_if<true, decltype(apply::deduce(std::declval<Ts>()...))>::type
|
||||
#else
|
||||
: decltype(apply::deduce(std::declval<Ts>()...))
|
||||
#endif
|
||||
{};
|
||||
};
|
||||
};
|
||||
|
||||
struct failure
|
||||
: failure_map<unpack_failure, F>
|
||||
{};
|
||||
|
||||
FIT_RETURNS_CLASS(unpack_adaptor);
|
||||
|
||||
template<class T>
|
||||
template<class T, class=typename std::enable_if<(
|
||||
is_unpackable<T>::value
|
||||
)>::type>
|
||||
constexpr auto operator()(T&& x) const
|
||||
FIT_RETURNS
|
||||
(
|
||||
detail::unpack_impl(FIT_MANGLE_CAST(const F&)(FIT_CONST_THIS->base_function(x)), fit::forward<T>(x))
|
||||
);
|
||||
|
||||
template<class T, class... Ts>
|
||||
template<class T, class... Ts, class=typename std::enable_if<(detail::and_<
|
||||
is_unpackable<T>, is_unpackable<Ts>...
|
||||
>::value)>::type>
|
||||
constexpr auto operator()(T&& x, Ts&&... xs) const FIT_RETURNS
|
||||
(
|
||||
detail::unpack_join(FIT_MANGLE_CAST(const F&)(FIT_CONST_THIS->base_function(x)), fit::forward<T>(x), fit::forward<Ts>(xs)...)
|
||||
|
||||
@@ -11,59 +11,96 @@ fit::static_<fit::unpack_adaptor<binary_class> > binary_unpack = {};
|
||||
FIT_STATIC_AUTO unary_unpack_constexpr = fit::unpack_adaptor<unary_class>();
|
||||
FIT_STATIC_AUTO binary_unpack_constexpr = fit::unpack_adaptor<binary_class>();
|
||||
|
||||
FIT_STATIC_AUTO unary_unpack_reveal = fit::reveal_adaptor<fit::unpack_adaptor<unary_class>>();
|
||||
FIT_STATIC_AUTO binary_unpack_reveal = fit::reveal_adaptor<fit::unpack_adaptor<binary_class>>();
|
||||
|
||||
FIT_TEST_CASE()
|
||||
{
|
||||
FIT_TEST_CHECK(3 == fit::unpack(unary_class())(std::make_tuple(3)));
|
||||
FIT_TEST_CHECK(3 == unary_unpack(std::make_tuple(3)));
|
||||
FIT_TEST_CHECK(3 == unary_unpack_reveal(std::make_tuple(3)));
|
||||
int ifu = 3;
|
||||
FIT_TEST_CHECK(3 == unary_unpack(std::tuple<int&>(ifu)));
|
||||
|
||||
FIT_STATIC_TEST_CHECK(3 == fit::unpack(unary_class())(std::make_tuple(3)));
|
||||
FIT_STATIC_TEST_CHECK(3 == unary_unpack_constexpr(std::make_tuple(3)));
|
||||
FIT_STATIC_TEST_CHECK(3 == unary_unpack_reveal(std::make_tuple(3)));
|
||||
}
|
||||
|
||||
FIT_TEST_CASE()
|
||||
{
|
||||
FIT_TEST_CHECK(3 == fit::unpack(unary_class())(fit::pack_decay(3)));
|
||||
FIT_TEST_CHECK(3 == unary_unpack(fit::pack_decay(3)));
|
||||
FIT_TEST_CHECK(3 == unary_unpack_reveal(fit::pack_decay(3)));
|
||||
int ifu = 3;
|
||||
FIT_TEST_CHECK(3 == unary_unpack(fit::pack_forward(ifu)));
|
||||
|
||||
FIT_STATIC_TEST_CHECK(3 == fit::unpack(unary_class())(fit::pack_decay(3)));
|
||||
FIT_STATIC_TEST_CHECK(3 == unary_unpack_constexpr(fit::pack_decay(3)));
|
||||
FIT_STATIC_TEST_CHECK(3 == unary_unpack_reveal(fit::pack_decay(3)));
|
||||
}
|
||||
|
||||
FIT_TEST_CASE()
|
||||
{
|
||||
FIT_TEST_CHECK(3 == fit::unpack(binary_class())(std::make_tuple(1, 2)));
|
||||
FIT_TEST_CHECK(3 == binary_unpack(std::make_tuple(1, 2)));
|
||||
FIT_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1, 2)));
|
||||
|
||||
FIT_TEST_CHECK(3 == fit::unpack(binary_class())(std::make_tuple(1), std::make_tuple(2)));
|
||||
FIT_TEST_CHECK(3 == binary_unpack(std::make_tuple(1), std::make_tuple(2)));
|
||||
FIT_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1), std::make_tuple(2)));
|
||||
|
||||
FIT_TEST_CHECK(3 == fit::unpack(binary_class())(std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
|
||||
FIT_TEST_CHECK(3 == binary_unpack(std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
|
||||
FIT_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
|
||||
|
||||
FIT_TEST_CHECK(3 == fit::unpack(binary_class())(std::make_tuple(), std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
|
||||
FIT_TEST_CHECK(3 == binary_unpack(std::make_tuple(), std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
|
||||
FIT_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(), std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
|
||||
|
||||
FIT_TEST_CHECK(3 == fit::unpack(binary_class())(std::make_tuple(1), std::make_tuple(), std::make_tuple(2), std::make_tuple()));
|
||||
FIT_TEST_CHECK(3 == binary_unpack(std::make_tuple(1), std::make_tuple(), std::make_tuple(2), std::make_tuple()));
|
||||
FIT_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1), std::make_tuple(), std::make_tuple(2), std::make_tuple()));
|
||||
|
||||
FIT_STATIC_TEST_CHECK(3 == fit::unpack(binary_class())(std::make_tuple(1, 2)));
|
||||
FIT_STATIC_TEST_CHECK(3 == binary_unpack_constexpr(std::make_tuple(1, 2)));
|
||||
FIT_STATIC_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1, 2)));
|
||||
|
||||
FIT_STATIC_TEST_CHECK(3 == fit::unpack(binary_class())(std::make_tuple(1), std::make_tuple(2)));
|
||||
FIT_STATIC_TEST_CHECK(3 == binary_unpack_constexpr(std::make_tuple(1), std::make_tuple(2)));
|
||||
FIT_STATIC_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1), std::make_tuple(2)));
|
||||
|
||||
FIT_STATIC_TEST_CHECK(3 == fit::unpack(binary_class())(std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
|
||||
FIT_STATIC_TEST_CHECK(3 == binary_unpack_constexpr(std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
|
||||
FIT_STATIC_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
|
||||
|
||||
FIT_STATIC_TEST_CHECK(3 == fit::unpack(binary_class())(std::make_tuple(), std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
|
||||
FIT_STATIC_TEST_CHECK(3 == binary_unpack_constexpr(std::make_tuple(), std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
|
||||
FIT_STATIC_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(), std::make_tuple(1), std::make_tuple(), std::make_tuple(2)));
|
||||
|
||||
FIT_STATIC_TEST_CHECK(3 == fit::unpack(binary_class())(std::make_tuple(1), std::make_tuple(), std::make_tuple(2), std::make_tuple()));
|
||||
FIT_STATIC_TEST_CHECK(3 == binary_unpack_constexpr(std::make_tuple(1), std::make_tuple(), std::make_tuple(2), std::make_tuple()));
|
||||
FIT_STATIC_TEST_CHECK(3 == binary_unpack_reveal(std::make_tuple(1), std::make_tuple(), std::make_tuple(2), std::make_tuple()));
|
||||
}
|
||||
|
||||
FIT_TEST_CASE()
|
||||
{
|
||||
auto p1 = fit::pack(1, 2);
|
||||
static_assert(fit::is_unpackable<decltype(p1)>::value, "Not unpackable");
|
||||
static_assert(fit::is_unpackable<decltype((p1))>::value, "Not unpackable");
|
||||
|
||||
auto p2 = fit::pack_forward(1, 2);
|
||||
static_assert(fit::is_unpackable<decltype(p2)>::value, "Not unpackable");
|
||||
static_assert(fit::is_unpackable<decltype((p2))>::value, "Not unpackable");
|
||||
|
||||
auto p3 = fit::pack_decay(1, 2);
|
||||
static_assert(fit::is_unpackable<decltype(p3)>::value, "Not unpackable");
|
||||
static_assert(fit::is_unpackable<decltype((p3))>::value, "Not unpackable");
|
||||
|
||||
static_assert(fit::is_unpackable<std::tuple<int>>::value, "Not unpackable");
|
||||
|
||||
static_assert(!fit::is_unpackable<int>::value, "Unpackable");
|
||||
static_assert(!fit::is_unpackable<void>::value, "Unpackable");
|
||||
}
|
||||
|
||||
FIT_STATIC_AUTO lambda_unary_unpack = fit::unpack(FIT_STATIC_LAMBDA(int x)
|
||||
|
||||
Reference in New Issue
Block a user