Mis*_*cha 7 c++ functional-programming c++11 stdtuple
我需要为任意元组中的每个元素调用 - template或overloaded函数.确切地说,我需要在元组中指定元素,因为它们在元组中指定.
例如.我有一个元组std::tuple<int, float> t{1, 2.0f};和一个功能
class Lambda{
public:
template<class T>
void operator()(T arg){ std::cout << arg << "; "; }
};
Run Code Online (Sandbox Code Playgroud)
我需要一些结构/函数Apply,如果调用它Apply<Lambda, int, float>()(Lambda(), t)会产生:
1; 2.0f;
Run Code Online (Sandbox Code Playgroud)
而不是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));
}
Run Code Online (Sandbox Code Playgroud)
编译代码但只打印第一个参数.但是,如果我用ForwardsApplicator专业化替换
template<class Func, class... Components>
class ForwardsApplicator < Func, 2, Components... >{...}
Run Code Online (Sandbox Code Playgroud)
它工作正常 - 但是,当然,仅适用于长度为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>());
}
Run Code Online (Sandbox Code Playgroud)
演示.
std::index_sequence和朋友是C++ 14,但它是一个纯库扩展,可以很容易地在C++ 11中实现.您可以在SO上轻松找到六个实现.
问题是size...(Components)不能用于未知类型列表的专门化Components.GCC抱怨错误:
Run Code Online (Sandbox Code Playgroud)prog.cpp:16:7: error: template argument 'sizeof... (Components)' involves template parameter(s) class ForwardsApplicator < Func, sizeof...(Components), Components... > { ^
我建议采用略有不同的方法.首先,将类型列表移动Components到模板参数中operator(),即:
template<class ...Components>
void operator()(Func func, const std::tuple<Components...>& t) {
...
}
Run Code Online (Sandbox Code Playgroud)
然后,反转调用顺序:首先执行递归调用,然后执行调用index-1(即调用最后一个元组元素).开始这个递归,index = sizeof...(Components)直到index = 0哪个是noop(所以专业化0,独立sizeof...(Components)于我开始讨论的问题).
要帮助调用此方法,请添加模板参数推导功能:
// General case (recursion)
template<class Func, size_t index>
class ForwardsApplicator{
public:
template<class ...Components>
void operator()(Func func, const std::tuple<Components...>& t){
ForwardsApplicator<Func, index - 1>()(func, t);
func(std::get<index - 1>(t));
}
};
// Special case (stop recursion)
template<class Func>
class ForwardsApplicator<Func, 0> {
public:
template<class ...Components>
void operator()(Func func, const std::tuple<Components...>& t){}
};
// Helper function for template type deduction
template<class Func, class ...Components>
void apply(Func func, const std::tuple<Components...>& t) {
ForwardsApplicator<Func, sizeof...(Components)>()(func, t);
}
Run Code Online (Sandbox Code Playgroud)
然后很容易调用,而无需在调用站点上使用任何模板参数:
apply(Lambda{}, std::make_tuple(1, 2.0f));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
297 次 |
| 最近记录: |