From a2bbe0410ba74d4006c7e6557eeb67fb08167aee Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 30 Apr 2015 00:54:07 -0500 Subject: [PATCH 1/4] Add is_unpackable trait --- fit/unpack.h | 25 ++++++++++++++++++++++++- test/unpack.cpp | 20 ++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/fit/unpack.h b/fit/unpack.h index 73eafb4..161a7e0 100644 --- a/fit/unpack.h +++ b/fit/unpack.h @@ -82,6 +82,7 @@ #include #include #include +#include #include #include #include @@ -89,9 +90,24 @@ namespace fit { template -struct unpack_sequence; +struct unpack_sequence +{ + typedef void not_unpackable; +}; + namespace detail { +template +struct is_unpackable_impl +: std::true_type +{}; + +template +struct is_unpackable_impl::not_unpackable +>::type> +: std::false_type +{}; template constexpr auto unpack_impl(F&& f, Sequence&& s) FIT_RETURNS @@ -108,6 +124,13 @@ constexpr auto unpack_join(F&& f, Sequences&&... s) FIT_RETURNS } +template +struct is_unpackable +: detail::is_unpackable_impl< + typename std::remove_cv::type>::type +> +{}; + template struct unpack_adaptor : F { diff --git a/test/unpack.cpp b/test/unpack.cpp index e53ce83..cfc2d86 100644 --- a/test/unpack.cpp +++ b/test/unpack.cpp @@ -66,6 +66,26 @@ FIT_TEST_CASE() FIT_STATIC_TEST_CHECK(3 == binary_unpack_constexpr(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::value, "Not unpackable"); + static_assert(fit::is_unpackable::value, "Not unpackable"); + + auto p2 = fit::pack_forward(1, 2); + static_assert(fit::is_unpackable::value, "Not unpackable"); + static_assert(fit::is_unpackable::value, "Not unpackable"); + + auto p3 = fit::pack_decay(1, 2); + static_assert(fit::is_unpackable::value, "Not unpackable"); + static_assert(fit::is_unpackable::value, "Not unpackable"); + + static_assert(fit::is_unpackable>::value, "Not unpackable"); + + static_assert(!fit::is_unpackable::value, "Unpackable"); + static_assert(!fit::is_unpackable::value, "Unpackable"); +} + FIT_STATIC_AUTO lambda_unary_unpack = fit::unpack(FIT_STATIC_LAMBDA(int x) { return x; From a542da3ae494ee41bdc579ecf73274f9e79c51a3 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 1 May 2015 00:11:33 -0500 Subject: [PATCH 2/4] Update doc about is_unpackable trait --- doc/src/unpack.md | 17 +++++++++++++++++ fit/unpack.h | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/doc/src/unpack.md b/doc/src/unpack.md index a3cad83..5200eec 100644 --- a/doc/src/unpack.md +++ b/doc/src/unpack.md @@ -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 + struct is_unpackable; + +Example +------- + + static_assert(fit::is_unpackable>::value, "Failed"); + unpack_sequence =============== diff --git a/fit/unpack.h b/fit/unpack.h index 161a7e0..8d42fe4 100644 --- a/fit/unpack.h +++ b/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 +/// struct is_unpackable; +/// +/// Example +/// ------- +/// +/// static_assert(fit::is_unpackable>::value, "Failed"); +/// /// unpack_sequence /// =============== /// From c12a91960f5bd1971d477d23ab97556b75c2c268 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 1 May 2015 00:21:53 -0500 Subject: [PATCH 3/4] Constrain unpack functionn using is_unpackable trait --- fit/detail/and.h | 23 +++++++++++++++++++++++ fit/detail/delegate.h | 7 +------ fit/unpack.h | 9 +++++++-- 3 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 fit/detail/and.h diff --git a/fit/detail/and.h b/fit/detail/and.h new file mode 100644 index 0000000..6399830 --- /dev/null +++ b/fit/detail/and.h @@ -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 + +namespace fit { namespace detail { + +template struct bool_seq {}; +template +struct and_ +: std::is_same, bool_seq<(Ts::value, true)...>>::type +{}; + +}} + +#endif \ No newline at end of file diff --git a/fit/detail/delegate.h b/fit/detail/delegate.h index c9690ac..8b969fe 100644 --- a/fit/detail/delegate.h +++ b/fit/detail/delegate.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -63,12 +64,6 @@ struct enable_if_constructible // static_assert(!std::is_same, std::unique_ptr > >::value, ""); }; -template struct bool_seq {}; -template -struct and_ -: std::is_same, bool_seq<(Ts::value, true)...>>::type -{}; - template struct is_default_constructible_helper : std::false_type diff --git a/fit/unpack.h b/fit/unpack.h index 8d42fe4..c4773e9 100644 --- a/fit/unpack.h +++ b/fit/unpack.h @@ -98,6 +98,7 @@ #include #include #include +#include #include #include #include @@ -161,14 +162,18 @@ struct unpack_adaptor : F FIT_RETURNS_CLASS(unpack_adaptor); - template + template::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(x)) ); - template + template, is_unpackable... + >::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(x), fit::forward(xs)...) From 1969dab3747c41faa9401f63e24822f166e774dd Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 1 May 2015 00:55:48 -0500 Subject: [PATCH 4/4] Add failure info to unpack --- fit/unpack.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ test/unpack.cpp | 17 +++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/fit/unpack.h b/fit/unpack.h index c4773e9..ef8eea3 100644 --- a/fit/unpack.h +++ b/fit/unpack.h @@ -98,6 +98,7 @@ #include #include #include +#include #include #include #include @@ -160,6 +161,49 @@ struct unpack_adaptor : F return always_ref(*this)(xs...); } + struct unpack_failure + { + template + struct apply + { + struct deducer + { + template + typename Failure::template of operator()(Ts&&...) const; + }; + + template::value + )>::type> + static auto deduce(T&& x) + FIT_RETURNS + ( + detail::unpack_impl(deducer(), fit::forward(x)) + ); + + template, is_unpackable... + >::value)>::type> + static auto deduce(T&& x, Ts&&... xs) FIT_RETURNS + ( + detail::unpack_join(deducer(), fit::forward(x), fit::forward(xs)...) + ); + + template + struct of +#if defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7 + : std::enable_if()...))>::type +#else + : decltype(apply::deduce(std::declval()...)) +#endif + {}; + }; + }; + + struct failure + : failure_map + {}; + FIT_RETURNS_CLASS(unpack_adaptor); template > binary_unpack = {}; FIT_STATIC_AUTO unary_unpack_constexpr = fit::unpack_adaptor(); FIT_STATIC_AUTO binary_unpack_constexpr = fit::unpack_adaptor(); +FIT_STATIC_AUTO unary_unpack_reveal = fit::reveal_adaptor>(); +FIT_STATIC_AUTO binary_unpack_reveal = fit::reveal_adaptor>(); + 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(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()