is_unpackable.hpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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. #ifndef BOOST_HOF_GUARD_IS_UNPACKABLE_HPP
  8. #define BOOST_HOF_GUARD_IS_UNPACKABLE_HPP
  9. /// is_unpackable
  10. /// =============
  11. ///
  12. /// This is a trait that can be used to detect whether the type can be called
  13. /// with `unpack`.
  14. ///
  15. /// Synopsis
  16. /// --------
  17. ///
  18. /// template<class T>
  19. /// struct is_unpackable;
  20. ///
  21. /// Example
  22. /// -------
  23. ///
  24. /// #include <boost/hof.hpp>
  25. /// #include <cassert>
  26. ///
  27. /// int main() {
  28. /// static_assert(boost::hof::is_unpackable<std::tuple<int>>::value, "Failed");
  29. /// }
  30. ///
  31. #include <boost/hof/unpack_sequence.hpp>
  32. #include <boost/hof/is_invocable.hpp>
  33. #include <boost/hof/always.hpp>
  34. #include <boost/hof/detail/static_const_var.hpp>
  35. #include <boost/hof/detail/unpack_tuple.hpp>
  36. namespace boost { namespace hof {
  37. namespace detail {
  38. struct unpack_impl_f
  39. {
  40. template<class F, class Sequence>
  41. constexpr auto operator()(F&& f, Sequence&& s) const BOOST_HOF_RETURNS
  42. (
  43. boost::hof::unpack_sequence<typename std::remove_cv<typename std::remove_reference<Sequence>::type>::type>::
  44. apply(BOOST_HOF_FORWARD(F)(f), BOOST_HOF_FORWARD(Sequence)(s))
  45. );
  46. };
  47. BOOST_HOF_DECLARE_STATIC_VAR(unpack_impl, unpack_impl_f);
  48. #if BOOST_HOF_CHECK_UNPACK_SEQUENCE
  49. struct private_unpack_type {};
  50. template<class Sequence>
  51. struct unpack_impl_result
  52. {
  53. static_assert(boost::hof::is_invocable<unpack_impl_f, decltype(boost::hof::always(private_unpack_type())), Sequence>::value,
  54. "Unpack is invalid for this sequence. The function used to unpack this sequence is not callable."
  55. );
  56. typedef decltype(boost::hof::detail::unpack_impl(boost::hof::always(private_unpack_type()), std::declval<Sequence>())) type;
  57. };
  58. template<class Sequence>
  59. struct is_proper_sequence
  60. : std::is_same<
  61. private_unpack_type,
  62. typename unpack_impl_result<Sequence>::type
  63. >
  64. {};
  65. #endif
  66. template<class Sequence, class=void>
  67. struct is_unpackable_impl
  68. : std::true_type
  69. {
  70. #if BOOST_HOF_CHECK_UNPACK_SEQUENCE
  71. static_assert(is_proper_sequence<Sequence>::value,
  72. "Unpack is invalid for this sequence. The function used to unpack this sequence does not invoke the function."
  73. );
  74. #endif
  75. };
  76. template<class Sequence>
  77. struct is_unpackable_impl<Sequence, typename detail::holder<
  78. typename unpack_sequence<Sequence>::not_unpackable
  79. >::type>
  80. : std::false_type
  81. {};
  82. }
  83. template<class Sequence>
  84. struct is_unpackable
  85. : detail::is_unpackable_impl<
  86. typename std::remove_cv<typename std::remove_reference<Sequence>::type>::type
  87. >
  88. {
  89. #if BOOST_HOF_CHECK_UNPACK_SEQUENCE
  90. typedef detail::is_unpackable_impl<
  91. typename std::remove_cv<typename std::remove_reference<Sequence>::type>::type
  92. > base;
  93. typedef std::conditional<base::value, detail::is_proper_sequence<Sequence>, std::true_type> check;
  94. static_assert(check::type::value,
  95. "Unpack is invalid for this sequence. The function used to unpack this sequence does not invoke the function."
  96. );
  97. #endif
  98. };
  99. }} // namespace boost::hof
  100. #endif