我需要为任意元组中的每个元素调用模板或重载函数。准确地说,我需要在元组中指定的元素上调用此函数。
例如。我有一个元组 std::tuple<int, float> t{1, 2.0f};
和功能
class Lambda{
public:
template<class T>
void operator()(T arg){ std::cout << arg << "; "; }
};
我需要一些结构/函数 Apply
, 如果像 Apply<Lambda, int, float>()(Lambda(), t)
这样调用会产生:
1; 2.0f;
而不是 2.0f; 1;
.
请注意,如果将“原始”参数包传递给函数,我知道解决方案,并且我知道如何以相反的顺序为元组执行此操作。但是以下部分特化的尝试 Apply
失败:
template<class Func, size_t index, class ...Components>
class ForwardsApplicator{
public:
void operator()(Func func, const std::tuple<Components...>& t){
func(std::get<index>(t));
ForwardsApplicator<Func, index + 1, Components...>()(func, t);
}
};
template<class Func, class... Components>
class ForwardsApplicator < Func, sizeof...(Components), Components... > {
public:
void operator()(Func func, const std::tuple<Components...>& t){}
};
int main{
ForwardsApplicator<Lambda, 0, int, float>()(Lambda{}, std::make_tuple(1, 2.0f));
}
代码已编译,但仅打印第一个参数。但是,如果我更换 ForwardsApplicator
特化
template<class Func, class... Components>
class ForwardsApplicator < Func, 2, Components... >{...}
它工作正常 - 但是,当然,仅适用于长度为 2 的元组。我如何做到这一点 - 如果可能的话,优雅地 - 对于任意长度的元组?
编辑:谢谢你们的回答!这三者都非常直截了当,并从所有可能的有利角度解释了问题。
最佳答案
这是integer_sequence
技巧的教科书案例。
template<class Func, class Tuple, size_t...Is>
void for_each_in_tuple(Func f, Tuple&& tuple, std::index_sequence<Is...>){
using expander = int[];
(void)expander { 0, ((void)f(std::get<Is>(std::forward<Tuple>(tuple))), 0)... };
}
template<class Func, class Tuple>
void for_each_in_tuple(Func f, Tuple&& tuple){
for_each_in_tuple(f, std::forward<Tuple>(tuple),
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>());
}
Demo .
std::index_sequence
和 friend 是 C++14,但它是一个纯库扩展,可以很容易地在 C++11 中实现。您可以轻松地在 SO 上找到六个实现。
关于c++ - 以自然(非反向)顺序将函数应用于 std::tuple 中的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28343591/