我正在尝试将无参数通用 lambda 转换为函数指针。此问题通常适用于泛型 lambda,其参数不依赖于模板实参。
示例尝试使用一个参数 () 来转换 lambda int,该参数在类型上与模板参数无关T。
#include <iostream>
int main()
{
auto lambda = []<class T>(int v) -> void
{
std::cout << typeid(T).name() << ' ' << static_cast<T>(v) << '\n';
};
// How do I cast lambda to a function pointer that uses operator(int)<char>
// This doesn't compile, I've reached this conclusion after examining this page https://en.cppreference.com/w/cpp/language/lambda
auto seeked_ptr_char = lambda.operator fptr_t<char>();
// Hacky solution :(
auto mptr_char = &decltype(lambda)::operator()<char>;
decltype(mptr_char) mptr_float = &decltype(lambda)::operator()<float>;
(lambda.*mptr_char)(48);
(lambda.*mptr_float)(52);
// This is okay (tho parameter is dependent on a template argument, which is not what we are looking for)
auto another_lambda = []<class T>(T v) -> void
{
std::cout << v << '\n';
};
void(*ptr_char)(char) = another_lambda;
ptr_char(50);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
不编译
x86-64 gcc 12.1 with -std=c++20 -O3
x86-64 clang 14.0.0 -std=c++20 -O3
如何将 lambda 转换为使用的函数指针
operator(int)<char>
TL;DR:你不知道。
首先,函数指针指向函数。模板还不是函数;只有当您向函数模板提供模板参数时,函数模板才会成为函数。函数指针可以指向函数模板的特定实例。但它不能指向函数模板。
从通用 lambda 到函数指针的转换依赖于调用模板转换函数。因此,lambda 实际上具有如下转换函数:
using func = void(int);
template<typename T>
operator func*();
Run Code Online (Sandbox Code Playgroud)
然而,这是一个模板转换函数。由于要转换的类型不提供模板参数,因此为了调用该函数,您必须显式提供该类型。这意味着您必须显式调用转换函数。
但考虑到您编写的代码,您已经解决了所有问题。这意味着你真正的问题是:
如果转换结果与模板参数没有任何关系,如何显式调用模板转换函数?
Lambda 在这里并不重要。这都是关于调用一种特殊的模板转换函数。
答案是……显然,你不知道。
type_name您可以通过语法显式调用类型转换函数object_name.operator type_name()。问题是标准中的这一行:
conversion-function-id 中的 conversion-type-id 是可能形成 conversion-type-id 的最长标记序列。
问题是如何lambda.operator fptr_t<char>()解析。看,fptr_t 可能是模板类的名称。因此,fptr_t<char> 可能是该类模板的专门化的名称。因此是“可能形成转换类型 IDfptr_t<char>的最长令牌序列”。
简而言之,编译器认为您正在尝试调用类型的转换函数fptr_t<char>。不是模板并不重要,编译器可以环顾四周并找出答案。fptr_t解析发生在任何此类思考之前。所以解析规则优先。整个fptr_t<char>文本被视为转换函数的类型名。
这一切都意味着,除非可以从要转换的类型单独推导出转换函数的模板参数,否则似乎不可能调用这样的转换函数。这样的转换函数是可以存在的;你可以声明这样的函数就可以了。但 C++ 缺乏任何与其实际交互的语法。
具有无法从函数参数推导的模板参数的 lambda 并不是特别有用的另一个原因。