2
0
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:
Paul
2015-05-09 22:54:06 -05:00
5 changed files with 170 additions and 9 deletions

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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)...)

View File

@@ -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)