在泛型lambda中使用模板参数
Using template parameter in a generic lambda
GCC允许以下语法作为扩展:
// a functional object that will add two like-type objects
auto add = [] <typename T> (T a, T b) { return a + b; };
在n3418,2012年通用lambdas的提案中,我们看到了允许上述内容的语法:
overload( []<class T>(T* p) {...},
然而,由于它是一个扩展,语法显然是不存在的(或不允许的)。当我们有auto时,在什么情况下以上内容会有用,为什么语法不存在(或不被允许)?
在我看来,C++14的多态lambda更简洁。
您可以复制您的样本情况的影响,如下所示:
struct A {};
struct B {};
int operator+(A, A) { return 1; }
int operator+(B, B) { return 2; }
int operator+(A, B) { return 3; }
int operator+(B, A) { return 4; }
int main() {
auto add = [](auto a, decltype(a) b) { return a + b; };
auto flexible_add = [](auto a, auto b) { return a + b; };
add(A{}, A{}); // works
add(B{}, B{}); // works
add(A{}, B{}); // doesn't work
flexible_add(A{}, A{}); // works
flexible_add(B{}, B{}); // works
flexible_add(A{}, B{}); // works
auto deref = [](auto *a) { return *a; };
int foo{};
A a;
B b;
deref(&foo); // works
deref(&a); // works
deref(&b); // works
deref(foo); // doesn't work
deref(a); // doesn't work
deref(b); // doesn't work
}
尽管在许多情况下GCC扩展的能力更强,但不仅仅是在您的用例中(它更自然地适合)。例如,关于非类型模板参数:
#include <cstddef>
#include <utility>
#include <iostream>
void print(std::initializer_list<std::size_t> il)
{
for (auto&& elem : il) std::cout << elem << std::endl;
}
int main()
{
auto indexed_lambda = [] <std::size_t... Is> (std::index_sequence<Is...>) { print({Is...}); };
indexed_lambda(std::make_index_sequence<5>{});
}
Coliru
复杂的通用参数类型:
void foo() {}
int main() {
auto accept_no_args_fun_only = [] <typename R> (R (*)()) {};
accept_no_args_fun_only(foo);
}
Coliru
变量:
#include <tuple>
#include <vector>
int main() {
auto accept_vector = [] (std::vector<auto> &&) {}; // Unconstrained placeholder from Concept TS, but not variadic
auto accept_tuple = [] <typename... Args> (std::tuple<Args...> &&) {};
accept_vector(std::vector{42});
accept_tuple(std::tuple{42});
}
Coliru
我不知道是否有关于包含泛型lambda的讨论,但我可以看到有人在思考,当当前语法涵盖了大多数用例、简洁且适合lambda的意图时,这种扩展是否值得包含,而lambda通常用于生成短代码片段。
编辑
GCC扩展已决定在第一次C++20 ISO标准会议上成为C++的一部分:
- http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0428r1.pdf
相关文章:
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 将参数传递给泛型 lambda 时复制构造函数不正确
- 可变参数泛型 lambda 和函数重载
- 以特征类型作为参数的泛型函数回调
- 具有静态大小数组作为参数的泛型 lambda
- 是否可以使用泛型枚举类型作为函数的参数?
- 将泛型函数及其参数传递给元函数
- 是否可以使用默认泛型参数在C++中定义 lambda?
- 具有泛型列表参数和委托的函数
- 在C++中,如何根据类中的参数返回不同的泛型类型
- 在泛型编程中选择类型参数
- 继承类中没有匹配的泛型委托作为 lambda 参数
- C++ 具有非泛型参数的模板专用化
- 声明一个模板函数,该函数接收两个泛型迭代器作为参数
- C++ 使用数组作为参数创建泛型函数
- 将泛型结构作为接口中的参数传递
- 使用具有不同输入参数和不同返回类型的模板的泛型函数
- 接受泛型列表类型对象的参数
- 无法推断模板参数 - 泛型函数
- 如何创建可变参数泛型 lambda