基于依赖类型的存在的重载

时间:2015-09-29 10:48:09

标签: c++ c++11 overloading sfinae overload-resolution

我有两个具有相同名称的模板化函数(foo)。它们的签名仅在第二个参数的类型上有所不同,这取决于模板参数T。让我感到惊讶的是,我可以使用它来重载,具体取决于T::AT::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的实现时,这是可能的。

3 个答案:

答案 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