gpt4 book ai didi

c++ - 这是lambda法律模板语法吗?

转载 作者:行者123 更新时间:2023-12-03 06:49:04 25 4
gpt4 key购买 nike

在重构一些遗留代码时,我遇到了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);
}

最佳答案

template<bool b>
auto lambda_pred = [] (S const & s) { return s.b == b; };
这实际上不是 template-lambda,而是分配给lambda的 variable template
这不等同于将模板参数添加到隐式声明的Closure struct中,后者将此lambda作为调用运算符(传统方法):
template<bool b>
struct StructPred { // NOT equivalent to this
bool operator()(S const & s) { return s.b == b; }
};

struct StructPred { // NOT equivalent to this either
template<bool b>
bool operator()(S const & s) { return s.b == b; }
};
相反,它等效于根据变量的模板参数创建不同的闭包。因此,对于 bool示例,这就像在以下类型之一的 operator()之间进行选择:
struct StructPred_true {
bool operator()(S const & s) { return s.b == true; }
}

struct StructPred_false {
bool operator()(S const & s) { return s.b == false; }
}
这种方法不允许部分特化,因此功能较弱。
这种方法可能不受欢迎的另一个原因是,它不能让您轻松访问Closure类型。
可以与匿名类 StructPredStructPred_true不同地使用 StructPred_falseC++ 20中的lambda模板如下所示:
auto lambda = []<bool b>(S const & s){ return s.b == b; };
相反,这等效于将Closure的 operator()模板化。

关于c++ - 这是lambda法律模板语法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63700581/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com