Is this method of function overloading for class hierarchies using templates safe?

Ok, this is a bit complicated, so please carry me. :)

We have this simple class hierarchy:

class A {};
class DA : public A {};
class DDA : public DA {};

And we have the following functions working on these classes:

void f(A x) {
  std::cout << "f A" << std::endl;
}
void f(DA x) {
  std::cout << "f DA" << std::endl;
}
void f(DDA x) {
  std::cout << "f DDA" << std::endl;
}

Now we want to add another function that processes DA a little differently.

(1) The first attempt might look like this:

void g(A t) {
  std::cout << "generic treatment of A" << std::endl;
  std::cout << "called from g: ";
  f(t);
}
void g(DA t) {
  std::cout << "special treatment of DA" << std::endl;
  std::cout << "called from g: ";
  f(t);
}

But calling this with the object of each of the classes obviously does not have the desired effect.

Call:

  A a; DA b; DDA c;
  g(a); g(b); g(c)

Result:

generic treatment of A
called from g: f A
special treatment of DA
called from g: f DA
special treatment of DA
called from g: f DA        //PROBLEM: g forgot that this DA was actually a DDA

(2) Therefore, we can try using templates instead:

template<typename T>
void h(T t) {
  std::cout << "generic treatment of A" << std::endl;
  std::cout << "called from h: ";
  f(t);
}

template<>
void h<>(DA t) {
  std::cout << "special treatment of DA" << std::endl;
  std::cout << "called from h: ";
  f(t);
}

that leads to:

generic treatment of A
called from h: f A
special treatment of DA
called from h: f DA
generic treatment of A    //PROBLEM: template specialization is not used
called from h: f DDA

, , , ? ( .) , , - , " ", , , . , (), DDA.

(3) , :

template<typename T>
void i(T t, void* magic) {
  std::cout << "generic treatment of A" << std::endl;
  std::cout << "called from i: ";
  f(t);
}

template<typename T>
void i(T t, DA* magic) {
  std::cout << "special treatment of DA" << std::endl;
  std::cout << "called from i: ";
  f(t);
}

, :

generic treatment of A
called from i: f A
special treatment of DA
called from i: f DA
special treatment of DA
called from i: f DDA

, : (a, & a); (b, & b); (c, & c);

:

  • , , ?
  • , ? ?
  • ?
  • ( , ...)

, .:)

+5
1

template<typename T>
void i(T t, DA* magic) {

, magic DA *. , , &b, &c, - --. void * , DA * void *, §13.3.3.2: 4:

13.3.3.2 [over.ics.rank]

[...]

4 : - , , , . , :

[...]

- B A, B* A* , B* void*, A* void* , B* void*.

, ; , i (a, &a):

template<typename T>
void j(T t) {
    i(t, &t);
}

; DA * , void * ; , .

std::enable_if :

template<typename T>
typename std::enable_if<!std::is_base_of<DA, T>::value>::type g(T t) {
  std::cout << "generic treatment of A" << std::endl;
  f(t);
}
template<typename T>
typename std::enable_if<std::is_base_of<DA, T>::value>::type g(T t) {
  std::cout << "special treatment of DA" << std::endl;
  f(t);
}
+4

All Articles