Mus*_*ang 0 c++ lambda templates
下面是一个典型的 C 函数,它采用经典函数指针作为参数:
int DoThingy( const char* stuff, int(*helper)(int))
{
int result = 0;
//...call helper...
return result;
}
Run Code Online (Sandbox Code Playgroud)
下面我用一个非捕获 lambda 来调用上面的内容,它神奇地“降级”为函数指针。在“A”处,转换是隐式的。在“B”处,它是明确的。都好。
void UseThingy()
{
auto lam = [](int)->int {
return 42;
};
int i;
i = DoThingy( "hello", lam); //"A" works
int (*ptr)(int) = lam;
i = DoThingy( "hello", ptr); //"B" works
}
Run Code Online (Sandbox Code Playgroud)
但在这个新示例中,回调函数的签名取决于模板类型:
template <typename T>
int DoThingy2( const char* stuff, int (*helper)(T))
{
int result = 0;
//...call helper...
return result;
}
Run Code Online (Sandbox Code Playgroud)
当我尝试使用上面的这个版本时,“C”行甚至无法编译。然而“D”处的显式版本是有效的。什么?为什么这些不一样?请注意,当我在“E”处给出显式模板参数时,它可以工作,但当然可以<int>
从 的签名推断出来lam
,对吧?
void UseThingy2()
{
auto lam = [](int)->int {
return 42;
};
int i;
i = DoThingy2( "hello", lam); //"C" won't compile
int (*ptr)(int) = lam;
i = DoThingy2( "hello", ptr); //"D" works
i = DoThingy2<int>( "hello", lam); //"E" works
}
Run Code Online (Sandbox Code Playgroud)
以下内容也无法编译,我希望它能编译:
i = DoThingy2( "hello", [](int)->int {return 42;}); //"F" won't compile
Run Code Online (Sandbox Code Playgroud)
我之前应该说的是,我需要将函数参数设置为默认值,以便在调用者未提供任何参数时使用0
内部版本。helper
请注意,这个问题与提议的重复问题明显不同。特别是关于可选参数,此外它还使用 C++17 模板选择功能提供了一组更好的答案。
您的问题是模板参数推导。当该进程运行时,不会发生任何转换,编译器获取提供的对象,获取它的类型,然后尝试从此类型推导出模板参数
在这种情况下,当函数lamba_object_from_main
需要函数指针时,它会获取(组成类型名称)。它无法推断,T
因为lamba_object_from_main
这是它唯一需要处理的东西。
您可以更改函数以仅接受第二个参数的任何内容,而不是使用函数指针,例如
template <typename Func>
int DoThingy( const char* stuff, Func helper)
{
int result = 0;
//...call helper...
return result;
}
Run Code Online (Sandbox Code Playgroud)
如果您想确保helper
具有特定的返回类型和参数,您可以限制模板,例如
template <typename Func, std::enable_if_t<is_invocable_r_v<int, Func, int>, bool> = true>
int DoThingy( const char* stuff, Func helper)
{
int result = 0;
//...call helper...
return result;
}
Run Code Online (Sandbox Code Playgroud)
如果您希望该功能是可选的,那么至少有几个选项。一是把模板改成
template <typename Func = int(*)(int),
std::enable_if_t<std::is_invocable_r_v<int, Func, int>, bool> = true>
int DoThingy2( const char*, Func helper = [](int i){ return internal_function(i); })
{
int result = 0;
helper(result);
return result;
}
Run Code Online (Sandbox Code Playgroud)
它使用默认的 lambda 来调用默认的内部函数
另一种选择是有两个重载,一个重载接受函数,另一个重载不接受函数,但调用与默认函数一起执行的重载,例如
template <typename Func, std::enable_if_t<is_invocable_r_v<int, Func, int>, bool> = true>
int DoThingy( const char* stuff, Func helper)
{
int result = 0;
//...call helper...
return result;
}
int DoThingy( const char* stuff)
{
return DoThingy(stuff, internal_function);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
135 次 |
最近记录: |