是否可以创建一个只有 lambda 的概念?
Is it possible to create a concept that is only a lambda?
从C++ 20开始,发布了约束模板和自动的概念。
我想创建一个只定义 lambda 的概念,这可能吗?
template <typename T>
concept lambda = /* ... */ ;
然后我可以这样申请:
int add(int x, int y) {
return x + y;
}
lambda auto func1 = []{ return 5; }; // constrain satisfied
lambda auto func2 = add; // constrain unsatisfied, compilation error.
我不知道你为什么想要这个,但我能想到的最接近的是:
template <typename T>
concept lambda = requires { &T::operator(); };
基本上,这需要 T
有呼叫操作员。这是可行的,因为这就是 lambda 的实现方式:它们为您提供一个对象,其类型由编译器生成 operator()
.
但是,这个概念接受不是 lambda 的东西,即具有调用运算符的用户定义结构,例如 std::function
、std::bind
、std::reference_wrapper
等。因此,这个概念基本上接受所有不是函数指针的可调用对象,这是 C++ 函数对象的一个奇怪分类。
可以在编译时得到T
的类型名,然后判断是否包含lambda的mangled name,在gcc中以<lambda
开头,在gcc中以(lambda
开头铿锵声:
虽然可行,但其实不推荐
#include <string_view>
template <typename T>
consteval bool is_lambda() {
std::string_view name = __PRETTY_FUNCTION__;
auto pos = name.find("T = ");
name.remove_prefix(pos + 4);
if (pos = name.rfind("::"); pos != name.npos)
name.remove_prefix(pos + 2);
#ifdef __clang__
return name.starts_with("(lambda");
#elif defined(__GNUC__)
return name.starts_with("<lambda");
#endif
}
template <class T>
concept lambda = is_lambda<T>();
从C++ 20开始,发布了约束模板和自动的概念。
我想创建一个只定义 lambda 的概念,这可能吗?
template <typename T>
concept lambda = /* ... */ ;
然后我可以这样申请:
int add(int x, int y) {
return x + y;
}
lambda auto func1 = []{ return 5; }; // constrain satisfied
lambda auto func2 = add; // constrain unsatisfied, compilation error.
我不知道你为什么想要这个,但我能想到的最接近的是:
template <typename T>
concept lambda = requires { &T::operator(); };
基本上,这需要 T
有呼叫操作员。这是可行的,因为这就是 lambda 的实现方式:它们为您提供一个对象,其类型由编译器生成 operator()
.
但是,这个概念接受不是 lambda 的东西,即具有调用运算符的用户定义结构,例如 std::function
、std::bind
、std::reference_wrapper
等。因此,这个概念基本上接受所有不是函数指针的可调用对象,这是 C++ 函数对象的一个奇怪分类。
可以在编译时得到T
的类型名,然后判断是否包含lambda的mangled name,在gcc中以<lambda
开头,在gcc中以(lambda
开头铿锵声:
虽然可行,但其实不推荐
#include <string_view>
template <typename T>
consteval bool is_lambda() {
std::string_view name = __PRETTY_FUNCTION__;
auto pos = name.find("T = ");
name.remove_prefix(pos + 4);
if (pos = name.rfind("::"); pos != name.npos)
name.remove_prefix(pos + 2);
#ifdef __clang__
return name.starts_with("(lambda");
#elif defined(__GNUC__)
return name.starts_with("<lambda");
#endif
}
template <class T>
concept lambda = is_lambda<T>();