【发布时间】:2017-09-27 14:07:34
【问题描述】:
假设我想使用以下语法创建自己的基于 lambda 的开关:
auto s = make_switch(std::pair{0, []{ return 0; }},
std::pair{1, []{ return 50; }},
std::pair{2, []{ return 100; }});
assert( s(0) == 0 );
assert( s(1) == 50 );
assert( s(2) == 100 );
我想使用 折叠表达式 以获得不需要递归的简洁实现。这个想法是生成类似于一堆嵌套if 语句的东西:
if(x == 0) return 0;
if(x == 1) return 50;
if(x == 2) return 100;
我想写这个:
// pseudocode
template <typename... Pairs>
auto make_switch(Pairs... ps)
{
return [=](int x)
{
( if(ps.first == x) return ps.second(), ... );
};
}
上面的代码不起作用,因为if(...){...} 不是表达式。然后我尝试使用&& 运算符:
template <typename... Pairs>
auto make_switch(Pairs... ps)
{
return [=](int x)
{
return ((ps.first == x && ps.second()), ...);
};
}
这确实编译,但返回ps.first == x && ps.second() 的结果,这是一个bool,而不是我想要的int 值。
我想要某种运算符,它是 逗号运算符 和 && 之间的组合:它应该计算并计算到运算符的 右侧如果 左侧 计算结果为 true。
我想不出任何技术可以让我以这样的方式实现它,我可以获取ps.second() 的返回值并将其传播给make_switch 返回的 lambda 的调用者。
是否可以使用 折叠表达式 实现这种“级联 ifs”模式?我只想评估所需数量的表达式,直到找到一个匹配的分支。
【问题讨论】:
-
由于您所有的
typename Pairs::second_type...都不同,我认为您只能通过递归来做到这一点。 -
@j6t: 但所有
decltype(ps.second)()都是一样的。我的意图是生成一组带有 fold 表达式 的if语句 -
他们不一样。您的示例调用中的每个 lambda 都是不同的类型。它们不可能相同,因为每个 lambda 的 operator() 实现都是不同的,即使它们看起来具有相同的签名。
-
@j6t:对不起,我搞砸了我的评论。我的意思是他们都返回
int。 (即decltype(ps.second())是一样的)
标签: c++ c++17 fold fold-expression