,
std::declval<func_type>()(std::forward<Ts>(ts)...)
f1 double (, operator()), std::pair (func_type ).
2 , , , , , , decltype(apply(...)) apply.
, , , , , .
, , : apply operator() compose_impl - f1 .
, :
#include <cstddef>
#include <type_traits>
#include <tuple>
#include <iostream>
#include <utility>
#include <functional>
template<typename> struct ret_hlp;
template<typename F, typename R, typename... Args> struct ret_hlp<R (F::*)(Args...) const>
{
using type = R;
};
template<typename F, typename R, typename... Args> struct ret_hlp<R (F::*)(Args...)>
{
using type = R;
};
template<typename ... Fs>
struct compose_impl
{
compose_impl(Fs&& ... fs) : functionTuple(std::forward_as_tuple(fs ...)) {}
using f1_type = typename std::remove_reference<typename std::tuple_element<0, std::tuple<Fs...>>::type>::type;
using ret_type = typename ret_hlp<decltype(&f1_type::operator())>::type;
template<size_t N, typename ... Ts>
ret_type apply(std::integral_constant<size_t, N>, Ts&& ... ts) const
{
return apply(std::integral_constant<size_t, N - 1>(), std::get<N> (functionTuple)(std::forward<Ts>(ts)...));
}
template<typename ... Ts>
ret_type apply(std::integral_constant<size_t, 0>, Ts&& ... ts) const
{
return std::get<0>(functionTuple)(std::forward<Ts>(ts)...);
}
template<typename ... Ts>
ret_type operator()(Ts&& ... ts) const
{
return apply(std::integral_constant<size_t, sizeof ... (Fs) - 1>(), std::forward<Ts>(ts)...);
}
std::tuple<Fs ...> functionTuple;
};
template<typename ... Fs>
compose_impl<Fs ...> compose(Fs&& ... fs)
{
return compose_impl<Fs ...>(std::forward<Fs>(fs) ...);
}
int main ()
{
auto f1 = [](std::pair<double,double> p) {return p.first + p.second; };
auto f2 = [](double x) {return std::make_pair(x, x + 1.0); };
auto f3 = [](double x, double y) {return x*y; };
auto g = compose(f1, f2, f3);
std::cout << g(2.0, 3.0) << std::endl;
return 0;
}
:
- GCC 4.9.1 Clang 3.5.0 ++ 11 Visual ++ 2013.
- ,
ret_hlp , operator() -, , . - ; , , :
compose lvalue ( ), functionTuple compose_impl . , , , .
EDIT: , :
, - Fs&& ... compose. F&&, ( ), A, :
- rvalue,
F A, A&& (, , compose); - lvalue,
F A&, A& &&, A& ( , , f1, - lvalues).
, compose_impl - ( )
compose_impl<lambda_1_type&, lambda_2_type&, lambda_3_type&>
, , functionTuple
std::tuple<lambda_1_type&, lambda_2_type&, lambda_3_type&>
- compose, , , functionTuple
std::tuple<lambda_1_type, lambda_2_type, lambda_3_type>
, , .
, , ; , .
, ( ), . - std::decay, , - , , compose_impl, .
- functionTuple, , :
std::tuple<typename std::decay<Fs>::type ...> functionTuple;
, , , .
, ; , "": -).
EDIT 2 OP: , , std::decay ( ret_type , ) , :
int f(int) { return 7; }
int main()
{
auto c1 = compose(&f, &f);
auto c2 = compose(f, f);
auto pf = f;
auto c3 = compose(pf, pf);
std::cout << std::is_same<decltype(c1.functionTuple), std::tuple<int(*)(int), int(*)(int)>>::value << '\n';
std::cout << std::is_same<decltype(c2.functionTuple), std::tuple<int(&)(int), int(&)(int)>>::value << '\n';
std::cout << std::is_same<decltype(c3.functionTuple), std::tuple<int(*&)(int), int(*&)(int)>>::value << '\n';
}
c3, , , , , . , , , ret_type.
std::decay F.