如何使用 lambda 作为参数传递模板函数中的函数类型参数?
How to infer a function type parameter in a template function with a lambda passed as argument?
考虑以下几点:
#include <utility>
#include <string>
template<typename>
class C;
template<typename R, typename T>
class C<R(&)(T)> {
public:
template<typename F>
C(F&& fun) {}
};
template<typename T>
C<T> makeC(T&& fun) {
return C<T>(std::forward<T>(fun));
}
int foo(int a){return a;}
int main() {
auto p1 = makeC(foo); // OK
auto p2 = C<int(&)(int)>([](int a){return a;}); // OK
// auto p3 = makeC([](int a){return a;}); // FAIL
}
p3
的声明失败,因为编译器无法从作为参数传递的 lambda 中推断类型 int(&)(int)
。 p1
可以,因为类型可以很容易地从函数 foo
中推断出来,而 p2
可以,因为类型是明确声明的。
它失败了:
error: invalid use of incomplete type 'class C<main()::<lambda(int)> >'
有没有办法让编译器在给定 lambda 的情况下正确推断函数类型?
P.S.: C++17 answers are also ok, if applicable.
实际问题是 lambda 函数有它自己的类型,不能简化为 R(&)(T)
。因此,C<T>
是编译器正确概述的不完整类型。
只要您使用非捕获 lambda,您就可以依赖于它们衰减为函数指针这一事实并执行此操作:
auto p3 = makeC(*(+[](int a){return a;}));
或者这样:
template<typename T>
auto makeC(T&& fun) -> C<decltype(*(+std::forward<T>(fun)))> {
return C<decltype(*(+std::forward<T>(fun)))>(std::forward<T>(fun));
}
另一种适用于捕获 lambda 的可能解决方案是:
#include <utility>
#include <string>
template<typename T>
class C: T {
template<typename F>
C(F&& fun): T{std::forward<F>(fun)} {}
};
template<typename R, typename T>
class C<R(&)(T)> {
public:
template<typename F>
C(F&& fun) {}
};
template<typename T>
C<T> makeC(T&& fun) {
return C<T>(std::forward<T>(fun));
}
int foo(int a){return a;}
int main() {
auto p1 = makeC(foo);
auto p2 = C<int(&)(int)>([](int a){return a;});
auto p3 = makeC([](int a){return a;});
}
这样,在处理 lambda 时,C
实际上继承自它并私下 包含 它的 operator()
。
考虑以下几点:
#include <utility>
#include <string>
template<typename>
class C;
template<typename R, typename T>
class C<R(&)(T)> {
public:
template<typename F>
C(F&& fun) {}
};
template<typename T>
C<T> makeC(T&& fun) {
return C<T>(std::forward<T>(fun));
}
int foo(int a){return a;}
int main() {
auto p1 = makeC(foo); // OK
auto p2 = C<int(&)(int)>([](int a){return a;}); // OK
// auto p3 = makeC([](int a){return a;}); // FAIL
}
p3
的声明失败,因为编译器无法从作为参数传递的 lambda 中推断类型 int(&)(int)
。 p1
可以,因为类型可以很容易地从函数 foo
中推断出来,而 p2
可以,因为类型是明确声明的。
它失败了:
error: invalid use of incomplete type 'class C<main()::<lambda(int)> >'
有没有办法让编译器在给定 lambda 的情况下正确推断函数类型?
P.S.: C++17 answers are also ok, if applicable.
实际问题是 lambda 函数有它自己的类型,不能简化为 R(&)(T)
。因此,C<T>
是编译器正确概述的不完整类型。
只要您使用非捕获 lambda,您就可以依赖于它们衰减为函数指针这一事实并执行此操作:
auto p3 = makeC(*(+[](int a){return a;}));
或者这样:
template<typename T>
auto makeC(T&& fun) -> C<decltype(*(+std::forward<T>(fun)))> {
return C<decltype(*(+std::forward<T>(fun)))>(std::forward<T>(fun));
}
另一种适用于捕获 lambda 的可能解决方案是:
#include <utility>
#include <string>
template<typename T>
class C: T {
template<typename F>
C(F&& fun): T{std::forward<F>(fun)} {}
};
template<typename R, typename T>
class C<R(&)(T)> {
public:
template<typename F>
C(F&& fun) {}
};
template<typename T>
C<T> makeC(T&& fun) {
return C<T>(std::forward<T>(fun));
}
int foo(int a){return a;}
int main() {
auto p1 = makeC(foo);
auto p2 = C<int(&)(int)>([](int a){return a;});
auto p3 = makeC([](int a){return a;});
}
这样,在处理 lambda 时,C
实际上继承自它并私下 包含 它的 operator()
。