onq*_*tam 6 c++ templates overloading type-traits c++11
为什么不能F推断proxy()?
它应该是可能的,因为我限制它 - 仅适用于返回的函数int.
#include <utility>
#include <iostream>
#include <type_traits>
using namespace std;
int foo(int bar) {
cout << "int" << endl;
return 2;
}
float foo(float bar) {
cout << "float" << endl;
return 1;
}
template <typename F, typename... Args>
typename enable_if<
is_same<
typename result_of<F(Args...)>::type,
int
>::value,
typename result_of<F(Args...)>::type
>::type
proxy(F func, Args&&... args) {
return func(forward<Args>(args)...);
}
int main() {
proxy(foo, 5);
}
Run Code Online (Sandbox Code Playgroud)
这是错误:
b.cpp:29:17: error: no matching function for call to 'proxy(<unresolved overloaded function type>, int)'
b.cpp:24:1: note: template argument deduction/substitution failed:
b.cpp:29:17: note: couldn't deduce template parameter 'F'
Run Code Online (Sandbox Code Playgroud)
问题是这样的:
proxy(foo, 5);
Run Code Online (Sandbox Code Playgroud)
编译器尝试推断 的类型foo,但有 2 个重载。当然,它可以Args...从推导5,但 的类型foo仍然是不可推导的,因为编译器在进行类型推导时不知道选择哪个重载。
F请注意,编译器需要知道函数签名中的类型,即此处,因此 SFINAE 发挥了它的魔力:
is_same<
typename result_of<F(Args...)>::type,
int
>::value,
Run Code Online (Sandbox Code Playgroud)
F它绝对没有办法从调用中正确推断出 的类型proxy(foo, 5),因此 SFINAE 无法启动。作为旁注,请注意 C++ 不能仅根据返回类型进行重载。因此,您无法仅根据返回类型来区分两个具有相同名称的函数。您需要以某种方式强制参数匹配,这将 SFINAE 排除非候选重载。
某种程度上相关:推导独立函数的返回类型
以及标准中的相关引用,强调我的(感谢@TC 指出):
14.8.2.1 从函数调用推导模板参数 [temp.deduct.call]/(6.2)
(6) 当 P 为函数类型、函数类型指针或成员函数类型指针时:
(6.1) 如果参数是包含一个或多个函数模板的重载集,则该参数将被视为非推导上下文。
(6.2) 如果参数是重载集(不包含函数模板),则尝试使用该集的每个成员进行试验参数推导。如果仅重载集成员之一的推导成功,则该成员将用作推导的参数值。如果对重载集的多个成员推导成功,则该参数将被视为非推导上下文。