mardi 29 septembre 2015

Overload based on existence of dependent type

I have two templated functions with the same name (foo). Their signatures differ only in the type of the second parameter, which is dependent on the template parameter T. What has surprised me is that I can use this to overload depending on whether T::A or T::B is an existent type. Is this something which is specially provided for in the standard (if so, a reference would be much appreciated), or am I just being dense in not recognising this as basic overload resolution?

#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'
}

For background, I discovered this was possible when looking into the implementation of std::enable_shared_from_this, which relies on this type of overloading.

Aucun commentaire:

Enregistrer un commentaire