arg.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*=============================================================================
  2. Copyright (c) 2014 Paul Fultz II
  3. arg.h
  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_FUNCTION_ARGS_H
  8. #define BOOST_HOF_GUARD_FUNCTION_ARGS_H
  9. #include <boost/hof/detail/seq.hpp>
  10. #include <boost/hof/returns.hpp>
  11. #include <boost/hof/detail/static_const_var.hpp>
  12. #include <utility>
  13. /// arg
  14. /// ===
  15. ///
  16. /// Description
  17. /// -----------
  18. ///
  19. /// The `arg` function returns a function object that returns the Nth argument
  20. /// passed to it. It actually starts at 1, so it is not the zero-based index
  21. /// of the argument.
  22. ///
  23. /// Synopsis
  24. /// --------
  25. ///
  26. /// template<class IntegralConstant>
  27. /// constexpr auto arg(IntegralConstant);
  28. ///
  29. /// template<std::size_t N, class... Ts>
  30. /// constexpr auto arg_c(Ts&&...);
  31. ///
  32. ///
  33. /// Example
  34. /// -------
  35. ///
  36. /// #include <boost/hof.hpp>
  37. /// #include <cassert>
  38. /// using namespace boost::hof;
  39. ///
  40. /// int main() {
  41. /// assert(arg(std::integral_constant<int, 3>())(1,2,3,4,5) == 3);
  42. /// }
  43. ///
  44. namespace boost { namespace hof {
  45. namespace detail {
  46. template<class T>
  47. struct perfect_ref
  48. {
  49. typedef T type;
  50. typedef typename std::remove_reference<T>::type value_type;
  51. T&& value;
  52. constexpr perfect_ref(value_type& x) noexcept
  53. : value(BOOST_HOF_FORWARD(T)(x))
  54. {}
  55. };
  56. template<std::size_t N>
  57. struct ignore
  58. {
  59. template<class T>
  60. constexpr ignore(T&&...) noexcept
  61. {}
  62. };
  63. template<std::size_t... N>
  64. struct args_at
  65. {
  66. template<class T, class... Ts>
  67. constexpr auto operator()(ignore<N>..., T x, Ts...) const
  68. BOOST_HOF_RETURNS(BOOST_HOF_FORWARD(typename T::type)(x.value));
  69. };
  70. template<std::size_t... N>
  71. constexpr args_at<N...> make_args_at(seq<N...>) noexcept
  72. {
  73. return {};
  74. }
  75. template<std::size_t N, class... Ts>
  76. constexpr auto get_args(Ts&&... xs) BOOST_HOF_RETURNS
  77. (
  78. boost::hof::detail::make_args_at(typename gens<N>::type())(nullptr, BOOST_HOF_RETURNS_CONSTRUCT(perfect_ref<Ts>)(xs)...)
  79. );
  80. template<class T, T N>
  81. struct make_args_f
  82. {
  83. template<class... Ts, class=typename std::enable_if<(N <= sizeof...(Ts))>::type>
  84. constexpr auto operator()(Ts&&... xs) const BOOST_HOF_RETURNS
  85. (
  86. boost::hof::detail::get_args<N>(BOOST_HOF_FORWARD(Ts)(xs)...)
  87. );
  88. };
  89. struct arg_f
  90. {
  91. template<class IntegralConstant>
  92. constexpr make_args_f<std::size_t, IntegralConstant::value> operator()(IntegralConstant) const noexcept
  93. {
  94. return make_args_f<std::size_t, IntegralConstant::value>();
  95. }
  96. };
  97. }
  98. #if BOOST_HOF_HAS_VARIABLE_TEMPLATES
  99. template<std::size_t N>
  100. BOOST_HOF_STATIC_CONSTEXPR detail::make_args_f<std::size_t, N> arg_c = {};
  101. #else
  102. template<std::size_t N, class... Ts>
  103. constexpr auto arg_c(Ts&&... xs) BOOST_HOF_RETURNS
  104. (
  105. boost::hof::detail::get_args<N>(BOOST_HOF_FORWARD(Ts)(xs)...)
  106. );
  107. #endif
  108. BOOST_HOF_DECLARE_STATIC_VAR(arg, detail::arg_f);
  109. }} // namespace boost::hof
  110. #endif