康桓瑋*_*康桓瑋 21 c++ lambda language-lawyer variadic-templates c++20
案例一:
考虑 lambdanoexcept说明符中的以下包扩展:
template <bool... B>
auto g() {
([]() noexcept(B) {}, ...);
}
Run Code Online (Sandbox Code Playgroud)
Clang 和 MSVC 接受此代码,但 GCC拒绝:
error: expansion pattern '<lambda>' contains no parameter packs
Run Code Online (Sandbox Code Playgroud)
这是一个有效的代码吗?我应该信任哪个编译器?它看起来像是与PR 47226相关的旧 GCC 错误。
案例2:
考虑 lambda 中的以下包扩展requires-clause:
template <bool... B>
auto g() {
([](auto) requires(B) {}, ...);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,Clang 和 MSVC 仍然接受此代码,而 GCC以相同的错误消息拒绝它。这只是同一个错误吗?
案例3:
考虑 lambda 模板列表中的以下包扩展:
template <typename... Args>
void g(Args...) {
([]<Args>(){}, ...);
}
Run Code Online (Sandbox Code Playgroud)
这次三个编译器都拒绝了相同的错误信息:
expansion pattern '<lambda>' contains no parameter packs
Run Code Online (Sandbox Code Playgroud)
与案例 1相比有什么不同吗?或者这是一个常见的错误?
有趣的练习!看看 C++20 草案,该标准首先区分了通用 lambda (7.5.5.5):
如果lambda表达式具有任何泛型参数类型占位符 (9.2.8.5),或者 lambda 具有template-parameter-list ,则 lambda 是泛型 lambda 。
Run Code Online (Sandbox Code Playgroud)int i = [](int i, auto a) { return i; }(3, 4); // OK: a generic lambda int j = []<class T>(T t, int i) { return i; }(3, 4); // OK: a generic lambda
因此,情况 1 具有非泛型 lambda,而情况 2 和 3 具有泛型 lambda。它不区分类型和非类型模板参数,所以我认为我同意 Yakk - Adam Nevraumont,所有三个都应该被接受。
Lambda 由一个未命名的、唯一的闭包类型表示,该类型具有函数调用运算符 ( operator())(泛型 lambda 的模板),其签名和约束由 lambda 表达式确定。编译器肯定可以使用类似于以下的代码来满足每种情况:
template<bool B>
struct closure {
auto operator()() const noexcept(B) {}
};
template <bool... B>
auto g() {
(closure<B>{}, ...);
}
Run Code Online (Sandbox Code Playgroud)
template<bool B>
struct closure {
auto operator()(auto) const requires(B) {}
};
template <bool... B>
auto g() {
(closure<B>{}, ...);
}
Run Code Online (Sandbox Code Playgroud)
template<typename T>
struct closure {
template<T>
auto operator()() const {}
};
template <typename... Args>
void g(Args...) {
(closure<Args>{}, ...);
}
Run Code Online (Sandbox Code Playgroud)
这些都在我的机器上编译,当前使用 gcc 11.2.1。
| 归档时间: |
|
| 查看次数: |
392 次 |
| 最近记录: |