在重构一些传统代码时,我发现了这个用于STL算法中的谓词的传统实现:
template<bool b>
struct StructPred {
bool operator()(S const & s) { return s.b == b; }
};
我感到疲惫并且达到了Ballmer峰值,所以我无意中将它重写为一个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);
}
template<bool b> struct { bool operator()(S const & s) { return s.b == b; } } struct_pred;
。 - Caleth