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