jeudi 2 juin 2016

Overloading a function for a generic type vs for a given type and its children

I am trying to write a pair of overloaded functions, one that must be called for a pointer to a type that is not a B or a child of B, and the second must be called for pointers to B and children of B. At first I tried to use specialization of the template for B, but this doesn't work for derived classes of B. So I looked up SFINAE and enable_if etc but couldn't get it to work.

The signature of the generic function is

(1) template<typename T> int f(T *t)

For the other I tried to use enable_if and is_base_of like so:

(2) template<typename T> int f(typename enable_if<is_base_of<B, T>::value, T>::type *t)

but always (1) gets called. I tried to replace (1) by the negation of (2):

(1b) template<typename T> int f(typename enable_if<!is_base_of<B, T>::value, T>::type *t)

and now I get errors for all Ts whether or not they are (children of) B.

What am I doing wrong? What is the solution?

Test code is as follows:

#include <type_traits>
#include <iostream>

using namespace std;

class B {};
class D : public B {};
class C {};

// (1)
/* template<typename T>
int f(T *t)
{ cout << "T\n"; } */

// (1b)
template<typename T>
int f(typename enable_if<!is_base_of<B, T>::value, T>::type *t)
{ cout << "T\n"; }

// (2)
template<typename T>
int f(typename enable_if<is_base_of<B, T>::value, T>::type *t)
{ cout << "B\n"; }

int main()
{
  B b;
  D d;
  C c;
  f(&b);    // Want B; get T with (1), dont compile with (1b)
  f(&d);    // Want B; get T with (1), dont compile with (1b)
  f(&c);    // Want T; get T with (1), dont compile with (1b)
  return 0;
}

Aucun commentaire:

Enregistrer un commentaire