我遇到了一个问题。当我使用类似 std::function<A(Fs...)>
的东西时它不起作用,但是 std::function<A(Fs..., B)>
确实有效。这是在 Clang 8.0 下;它在 GCC 下都不起作用。
这是示例:
#include <functional>
template<typename A, typename B, typename ...Fs>
void func_tmpl1(std::function<A(Fs..., B)> callable)
{
}
template<typename A, typename ...Fs>
void func_tmpl2(std::function<A(Fs...)> callable)
{
}
class Cls1{};
void func0(std::function<void(float, Cls1)> callable)
{
}
int main()
{
std::function<void(float, Cls1)> f1 = [](float a, Cls1 b){};
func0(f1);
func0([](float a, Cls1 b){});
func_tmpl1<void, Cls1, float>(f1); // fails in GCC
func_tmpl2<void, float, Cls1>(f1);
func_tmpl1<void, Cls1, float>( // fails in GCC
[](float a, Cls1 b)
{
}
);
func_tmpl2<void, float, Cls1>( // fails in both
[](float a, Cls1 b)
{}
);
return 0;
}
上 Godbolt ,我们可以看到 GCC 总是失败,但 Clang 只在最后一次函数调用时失败。谁能解释这里发生了什么?
最佳答案
为方便起见,让我们在代码#1、#2 和#3 中调用三个失败的调用。
问题是,当显式指定模板参数包对应的模板参数时,模板参数包是否仍然参与模板参数推导,如果参与,推导失败是否会使整个调用格式错误?
来自 [temp.arg.explicit]/9 :
Template argument deduction can extend the sequence of template arguments corresponding to a template parameter pack, even when the sequence contains explicitly specified template arguments.
我们可以推断仍然应该执行模板参数推导。
在
func_tmpl1
的声明中, std::function<A(Fs..., B)>
是非推导上下文( [temp.deduct.type]/9 :“如果 P 的模板参数列表包含不是最后一个模板参数的包展开,则整个模板参数列表都是非推导上下文。”),因此模板参数推导为 Fs
应该被忽略,#1 和 #2 都是格式良好的。有一个GCC bug report .对于#3,模板参数推导显然失败(
std::function<A(Fs...)>
vs lambda 类型),但是推导失败真的会使代码格式错误吗?在我看来,这个标准不清楚,还有一个related issue .从 CWG 的回应来看,#3 确实格式错误。
关于c++ - 为什么模板参数解包有时不适用于 std::function?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61281556/