Consider the case of a templated function with variadic template arguments:
template Tret func(const T&... t);
I am evaluating MSVS 2013RC, and it failed to compile some of the previous solutions proposed here in some cases. For example, MSVS will fail to compile "auto" returns if there are too many function parameters, because of a namespace imbrication limit (I sent that info to Microsoft to have it corrected). In other cases, we need access to the function's return, although that can also be done with a lamda: the following two examples give the same result..
apply_tuple([&ret1](double a){ret1 = cos(a); }, std::make_tuple(.2));
ret2 = apply_tuple((double(*)(double))cos, std::make_tuple(.2));
And thanks again to those who posted answers here before me, I wouldn't have gotten to this without it... so here it is:
template
struct apply_impl {
template
static inline auto apply_tuple(F&& f, T&& t, A&&... a)
-> decltype(apply_impl::apply_tuple(std::forward(f), std::forward(t),
std::get(std::forward(t)), std::forward(a)...)) {
return apply_impl::apply_tuple(std::forward(f), std::forward(t),
std::get(std::forward(t)), std::forward(a)...);
}
template
static inline auto apply_tuple(C*const o, F&& f, T&& t, A&&... a)
-> decltype(apply_impl::apply_tuple(o, std::forward(f), std::forward(t),
std::get(std::forward(t)), std::forward(a)...)) {
return apply_impl::apply_tuple(o, std::forward(f), std::forward(t),
std::get(std::forward(t)), std::forward(a)...);
}
};
// This is a work-around for MSVS 2013RC that is required in some cases
#if _MSC_VER <= 1800 /* update this when bug is corrected */
template<>
struct apply_impl<6> {
template
static inline auto apply_tuple(F&& f, T&& t, A&&... a)
-> decltype(std::forward(f)(std::get<0>(std::forward(t)), std::get<1>(std::forward(t)), std::get<2>(std::forward(t)),
std::get<3>(std::forward(t)), std::get<4>(std::forward(t)), std::get<5>(std::forward(t)), std::forward(a)...)) {
return std::forward(f)(std::get<0>(std::forward(t)), std::get<1>(std::forward(t)), std::get<2>(std::forward(t)),
std::get<3>(std::forward(t)), std::get<4>(std::forward(t)), std::get<5>(std::forward(t)), std::forward(a)...);
}
template
static inline auto apply_tuple(C*const o, F&& f, T&& t, A&&... a)
-> decltype((o->*std::forward(f))(std::get<0>(std::forward(t)), std::get<1>(std::forward(t)), std::get<2>(std::forward(t)),
std::get<3>(std::forward(t)), std::get<4>(std::forward(t)), std::get<5>(std::forward(t)), std::forward(a)...)) {
return (o->*std::forward(f))(std::get<0>(std::forward(t)), std::get<1>(std::forward(t)), std::get<2>(std::forward(t)),
std::get<3>(std::forward(t)), std::get<4>(std::forward(t)), std::get<5>(std::forward(t)), std::forward(a)...);
}
};
#endif
template<>
struct apply_impl<0> {
template
static inline auto apply_tuple(F&& f, T&&, A&&... a)
-> decltype(std::forward(f)(std::forward(a)...)) {
return std::forward(f)(std::forward(a)...);
}
template
static inline auto apply_tuple(C*const o, F&& f, T&&, A&&... a)
-> decltype((o->*std::forward(f))(std::forward(a)...)) {
return (o->*std::forward(f))(std::forward(a)...);
}
};
// Apply tuple parameters on a non-member or static-member function by perfect forwarding
template
inline auto apply_tuple(F&& f, T&& t)
-> decltype(apply_impl::type>::value>::apply_tuple(std::forward(f), std::forward(t))) {
return apply_impl::type>::value>::apply_tuple(std::forward(f), std::forward(t));
}
// Apply tuple parameters on a member function
template
inline auto apply_tuple(C*const o, F&& f, T&& t)
-> decltype(apply_impl::type>::value>::apply_tuple(o, std::forward(f), std::forward(t))) {
return apply_impl::type>::value>::apply_tuple(o, std::forward(f), std::forward(t));
}