• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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