我有两个具有相同名称的模板化函数(foo
)。它们的签名仅在第二个参数的类型上有所不同,这取决于模板参数T
。让我感到惊讶的是,我可以使用它来重载,具体取决于T::A
或T::B
是否存在类型。这是标准中特别提供的内容(如果是这样,会非常感谢参考),或者我只是在密集而不认为这是基本的重载分辨率?
#include <iostream>
using namespace std;
template<typename T>
void foo(T t, typename T::A* a = 0) {
cout << "Had an A" << endl;
}
template<typename T>
void foo(T t, typename T::B* b = 0) {
cout << "Had a B" << endl;
}
struct HasAnAType {
typedef int A;
};
struct HasABType {
typedef int B;
};
struct HasAAndBTypes {
typedef int A;
typedef int B;
};
int main() {
HasAnAType a;
HasABType b;
HasAAndBTypes ab;
foo(a); // prints "Had an A"
foo(b); // prints "Had a B"
foo(ab); // won't compile: 'ambiguous call to overloaded function'
}
对于后台,我发现在查看依赖于此类重载的std::enable_shared_from_this
的实现时,这是可能的。
答案 0 :(得分:4)
感谢SFINAE,当void foo(T t, typename T::B* b = 0)
不存在时,重载T::B
被删除(类似于T::A
)
因此,当两者都可用时,两个重载都是可行的,因此调用是不明确的。
答案 1 :(得分:3)
这是规范定义重载决策的方式:
过载分辨率是一种选择最佳功能的机制 调用给出一个表达式列表,这些表达式将作为参数的参数 调用和一组可以根据的调用的候选函数 电话的背景。
在所有情况下,最佳功能的选择是相同的:首先,a 候选函数的子集(具有正确数字的函数) 选择参数并满足某些其他条件) 一套可行的功能。然后选择最佳可行功能 基于匹配每个所需的隐式转换序列 每个可行函数的相应参数的参数。
对于模板功能,还有其他规则:
对于每个功能模板,如果参数扣除和检查 成功,模板参数(推断和/或显式)用于 合成单个函数模板的声明 添加到候选函数中的特化 用于重载分辨率。如果,对于给定的函数模板, 参数推导失败,没有将这样的函数添加到集合中 该模板的候选函数。
如果模板函数的重载分辨率过高,这些规则会导致所谓的SFINAE。
答案 2 :(得分:1)
你是对的,这不是常规的&#39;超载。它被称为SFINAE。更多信息请访问:https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error