Ответ 1
Предполагая, что вы передаете нечто похожее на общую лямбда, то есть объект функции с перегруженным оператором вызова функции:
#include <iostream>
struct Func
{
template<class T>
void operator()(T p)
{
std::cout << __PRETTY_FUNCTION__ << " : " << p << "\n";
}
};
Вы можете создать массив указателей функций:
#include <tuple>
template<int... Is> struct seq {};
template<int N, int... Is> struct gen_seq : gen_seq<N-1, N-1, Is...> {};
template<int... Is> struct gen_seq<0, Is...> : seq<Is...> {};
template<int N, class T, class F>
void apply_one(T& p, F func)
{
func( std::get<N>(p) );
}
template<class T, class F, int... Is>
void apply(T& p, int index, F func, seq<Is...>)
{
using FT = void(T&, F);
static constexpr FT* arr[] = { &apply_one<Is, T, F>... };
arr[index](p, func);
}
template<class T, class F>
void apply(T& p, int index, F func)
{
apply(p, index, func, gen_seq<std::tuple_size<T>::value>{});
}
Пример использования:
int main()
{
std::tuple<int, double, char, double> t{1, 2.3, 4, 5.6};
for(int i = 0; i < 4; ++i) apply(t, i, Func{});
}
clang++ также принимает расширение, применяемое к шаблону, содержащему лямбда-выражение:
static FT* arr[] = { [](T& p, F func){ func(std::get<Is>(p)); }... };
(хотя я должен признать, что выглядит действительно странно)
g++ 4.8.1 отклоняет это.