我很难弄清楚这个示例代码中导致替换失败的原因:
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)
{
}
主要地方:
call1<int, int, float>(3, 4, 5.5, f); // Ok.
call2<int, int, float>(f); // Substitution failure.
编译器说:
template argument deduction/substitution failed: mismatched types 'std::function<bool(Params ...)>' and 'bool (*)(int, int, float)'
call2<int, int, float>(f);
^
令我感到困惑的是call1有效,而call2没有。 有小费吗? =)
答案 0 :(得分:3)
首先:您可以指定少于您使用的参数,让编译器推断出其余参数:
template <typename ...Params>
void func1(Params... params);
func1<int, int>(1, 2, 3); // calls func1<int, int, int>
这意味着Params
在您调用时仍然可以添加额外的类型。但是如果你拿到函数地址,就会定义并关闭它:
auto x = func1<int, int>;
x(1, 2, 3); // not possible
直接拨打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
编译器能够推断出你有3个整数,因为你刚给他发了3个整数。这样,最后一个参数必须是std::function<bool(int, int, int)>
,因为我们完全推断出Params...
的含义,并且没有更多类型的空间。
现在有问题的案例:
template <typename... Params>
void call2(std::function<bool(Params...)> func);
call2<int, int, int>(f);
在这里,您告知编译器Params
的前3个元素都是整数。 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.
在这里你强迫Params
完成。没有扣除评估。虽然很难看,但这也有效:
(&call2<int, int, int>)(f);
答案 1 :(得分:1)
编译器无法使用当前代码推断出类型(即使函数指针可隐式转换为std::function
)。您可以创建一个traits类来帮助推断出正确的类型。
template <typename... Params>
struct func_traits {
using func_type = std::function<bool(Params...)>;
};
template <typename ...Params>
void call2(typename func_traits<Params...>::func_type func) {}
答案 2 :(得分:0)
表达式f
的类型是指向函数的指针,即bool (*)(int, int, float)
。然而,call2
模板的显式实例化具有类型void foo (std::function<bool (int, int, float)> )
,即参数类型不同,因此不匹配。
解决方法:
auto x = call2<int, int, float>;
x(f);
利用从函数指针构造std::function
的可能性。