【发布时间】:2020-12-21 07:56:11
【问题描述】:
在重构一些遗留代码时,我遇到了这种用于 STL 算法的谓词的传统实现:
template<bool b>
struct StructPred {
bool operator()(S const & s) { return s.b == b; }
};
我累了,撞到了鲍尔默峰,所以我不小心把它改成了这样的 lambda,看起来很自然,也很有效:
template<bool b>
auto lambda_pred = [] (S const & s) { return s.b == b; };
后来我意识到我从未见过这样的模板 lambda。我在 cppreference 或 stackoverflow 上找不到类似的东西。生成模板 lambda 的规范方法似乎是将它们包装在模板结构或模板函数中。 C++20 为 lambda 引入了命名模板参数,但这是一种不同的语法(在捕获括号之后)。
现在我的问题是:这是合法的语法吗?它在任何地方都有记录吗?它甚至是 lambda 还是其他什么?与包装替代品相比,是否有任何影响或副作用?当这可行时,为什么每个人都推荐包装器实现?我错过了什么明显的东西吗?
完整的工作测试代码如下和godbolt。只是为了确保我还添加了一个类型模板参数版本。 MSVC、GCC 和 clang 对这段代码很满意。
#include <vector>
#include <algorithm>
struct S {
bool b = false;
};
// classic function object
template<bool b>
struct StructPred {
bool operator()(S const & s) { return s.b == b; }
};
// template function producing a lambda
template<bool b>
auto make_pred() {
return [] (S const & s) { return s.b == b; };
}
// direct template lambda
template<bool b>
auto lambda_pred = [] (S const & s) { return s.b == b; };
// also with type params
template<typename T, bool b>
auto lambda_pred_t = [] (T const & t) { return t.b == b; };
std::pair<size_t, size_t> count1(std::vector<S> const & v) {
return {
std::count_if(v.begin(), v.end(), StructPred<true>{}),
std::count_if(v.begin(), v.end(), StructPred<false>{})
};
}
std::pair<size_t, size_t> count2(std::vector<S> const & v) {
return {
std::count_if(v.begin(), v.end(), make_pred<true>()),
std::count_if(v.begin(), v.end(), make_pred<false>())
};
}
std::pair<size_t, size_t> count3(std::vector<S> const & v) {
return {
std::count_if(v.begin(), v.end(), lambda_pred<true>),
std::count_if(v.begin(), v.end(), lambda_pred<false>)
};
}
std::pair<size_t, size_t> count4(std::vector<S> const & v) {
return {
std::count_if(v.begin(), v.end(), lambda_pred_t<S, true>),
std::count_if(v.begin(), v.end(), lambda_pred_t<S, false>)
};
}
void test() {
std::vector<S> v{3};
v[1].b = true;
// all implementations correctly return {1,2}
auto c1 = count1(v);
auto c2 = count2(v);
auto c3 = count3(v);
auto c4 = count4(v);
}
【问题讨论】:
标签: c++ templates lambda c++14