1/*============================================================================= 2 Copyright (c) 2016 Paul Fultz II 3 is_unpackable.hpp 4 Distributed under the Boost Software License, Version 1.0. (See accompanying 5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6==============================================================================*/ 7 8#ifndef BOOST_HOF_GUARD_IS_UNPACKABLE_HPP 9#define BOOST_HOF_GUARD_IS_UNPACKABLE_HPP 10 11/// is_unpackable 12/// ============= 13/// 14/// This is a trait that can be used to detect whether the type can be called 15/// with `unpack`. 16/// 17/// Synopsis 18/// -------- 19/// 20/// template<class T> 21/// struct is_unpackable; 22/// 23/// Example 24/// ------- 25/// 26/// #include <boost/hof.hpp> 27/// #include <cassert> 28/// 29/// int main() { 30/// static_assert(boost::hof::is_unpackable<std::tuple<int>>::value, "Failed"); 31/// } 32/// 33 34#include <boost/hof/unpack_sequence.hpp> 35#include <boost/hof/is_invocable.hpp> 36#include <boost/hof/always.hpp> 37#include <boost/hof/detail/static_const_var.hpp> 38#include <boost/hof/detail/unpack_tuple.hpp> 39 40namespace boost { namespace hof { 41 42namespace detail { 43 44struct unpack_impl_f 45{ 46 template<class F, class Sequence> 47 constexpr auto operator()(F&& f, Sequence&& s) const BOOST_HOF_RETURNS 48 ( 49 boost::hof::unpack_sequence<typename std::remove_cv<typename std::remove_reference<Sequence>::type>::type>:: 50 apply(BOOST_HOF_FORWARD(F)(f), BOOST_HOF_FORWARD(Sequence)(s)) 51 ); 52}; 53 54BOOST_HOF_DECLARE_STATIC_VAR(unpack_impl, unpack_impl_f); 55 56#if BOOST_HOF_CHECK_UNPACK_SEQUENCE 57struct private_unpack_type {}; 58template<class Sequence> 59struct unpack_impl_result 60{ 61 static_assert(boost::hof::is_invocable<unpack_impl_f, decltype(boost::hof::always(private_unpack_type())), Sequence>::value, 62 "Unpack is invalid for this sequence. The function used to unpack this sequence is not callable." 63 ); 64 typedef decltype(boost::hof::detail::unpack_impl(boost::hof::always(private_unpack_type()), std::declval<Sequence>())) type; 65}; 66 67template<class Sequence> 68struct is_proper_sequence 69: std::is_same< 70 private_unpack_type, 71 typename unpack_impl_result<Sequence>::type 72> 73{}; 74#endif 75template<class Sequence, class=void> 76struct is_unpackable_impl 77: std::true_type 78{ 79#if BOOST_HOF_CHECK_UNPACK_SEQUENCE 80 static_assert(is_proper_sequence<Sequence>::value, 81 "Unpack is invalid for this sequence. The function used to unpack this sequence does not invoke the function." 82 ); 83#endif 84}; 85 86template<class Sequence> 87struct is_unpackable_impl<Sequence, typename detail::holder< 88 typename unpack_sequence<Sequence>::not_unpackable 89>::type> 90: std::false_type 91{}; 92 93} 94 95template<class Sequence> 96struct is_unpackable 97: detail::is_unpackable_impl< 98 typename std::remove_cv<typename std::remove_reference<Sequence>::type>::type 99> 100{ 101#if BOOST_HOF_CHECK_UNPACK_SEQUENCE 102typedef detail::is_unpackable_impl< 103 typename std::remove_cv<typename std::remove_reference<Sequence>::type>::type 104> base; 105 106typedef std::conditional<base::value, detail::is_proper_sequence<Sequence>, std::true_type> check; 107static_assert(check::type::value, 108 "Unpack is invalid for this sequence. The function used to unpack this sequence does not invoke the function." 109); 110#endif 111}; 112 113}} // namespace boost::hof 114 115#endif 116