use*_*691 8 variadic-templates c++11
我很难弄清楚这个示例代码中导致替换失败的原因:
bool f(int a, int b, float c)
{
printf("%d %d %f", a, b, c);
return true;
}
template <typename ...Params>
void call1(Params... params, std::function<bool(Params...)> func)
{
func(params...);
}
template <typename ...Params>
void call2(std::function<bool(Params...)> func)
{
}
Run Code Online (Sandbox Code Playgroud)
主要的地方:
call1<int, int, float>(3, 4, 5.5, f); // Ok.
call2<int, int, float>(f); // Substitution failure.
Run Code Online (Sandbox Code Playgroud)
编译器说:
template argument deduction/substitution failed: mismatched types 'std::function<bool(Params ...)>' and 'bool (*)(int, int, float)'
call2<int, int, float>(f);
^
Run Code Online (Sandbox Code Playgroud)
令我感到困惑的是call1有效,而call2没有.有小费吗?=)
第一:您可以指定比您使用的参数更少的参数,然后让编译器推断出其余的参数:
template <typename ...Params>
void func1(Params... params);
func1<int, int>(1, 2, 3); // calls func1<int, int, int>
Run Code Online (Sandbox Code Playgroud)
当您调用它时,这意味着Params仍然可以添加额外的类型。但是如果你获取函数地址,它就会被定义并关闭:
auto x = func1<int, int>;
x(1, 2, 3); // not possible
Run Code Online (Sandbox Code Playgroud)
当您call1直接调用函数时:
template <typename... Params>
void call1(Params... params, std::function<bool(Params...)> func);
call1<int, int, int>(1, 2, 3, f);
call1<int>(1, 2, 3, f); // same as before
call1(1, 2, 3, f); // same as before
Run Code Online (Sandbox Code Playgroud)
编译器能够推断出您正好有 3 个整数,因为您刚刚向他发送了 3 个整数。这样最后一个参数一定是std::function<bool(int, int, int)>因为我们完全推导了Params...含义并且没有空间容纳更多类型。
现在有问题的情况:
template <typename... Params>
void call2(std::function<bool(Params...)> func);
call2<int, int, int>(f);
Run Code Online (Sandbox Code Playgroud)
这里你告诉编译器 的前 3 个元素Params都是整数。Params = {int, int, int, ...}。请注意,如果推论表明如此,它仍然可以添加其他内容。替换我们有:std::function<bool(int, int, int, ...)> func。除非您显式传递(完全匹配),否则编译器不可能知道这个不完整类型的含义std:function。它还不知道它可以有一个构造函数来获取您提供的函数指针,因此存在不匹配。现在编译器没有足够的数据来决定是否需要更多类型Params。失败。
但请注意这个有趣的案例:
auto x = call2<int, int, int>;
x(f); // x is exactly void(*)(std::function<bool(int, int, int)>). No doubts.
Run Code Online (Sandbox Code Playgroud)
在这里你强迫自己Params完整。没有扣除可以评估。虽然丑陋,但这也有效:
(&call2<int, int, int>)(f);
Run Code Online (Sandbox Code Playgroud)