Thomas Eding Thomas Eding - 1 month ago 11
C++ Question

Covariant Return Type With Template Container

Is it possible to make the following work? Basically I want Ptr<B> to be an acceptable return type replacement for Ptr<A>.

template<typename T>
class Ptr {
public:
explicit Ptr (T * ptr) : ptr(ptr) {}
T * ptr;
};


class A {
virtual Ptr<A> foo () {
return Ptr<A>(NULL);
}
};

class B : public A {
virtual Ptr<B> foo () { // BAD! Ptr<B> is not compatable
return Ptr<B>(NULL);
}
};

Answer

According to the standard:

The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. If a function D::f overrides a function B::f, the return types of the functions are covariant if they satisfy the following criteria:

  • both are pointers to classes or references to classes
  • the class in the return type of B::f is the same class as the class in the return type of D::f or, is an unambiguous direct or indirect base class of the class in the return type of D::f and is accessible in D
  • both pointers or references have the same cv-qualification and the class type in the return type of D::f has the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.

So in your example the return types are not really covariant (they are not pointers nor references) and moreover Ptr<B> and Ptr<A> are unrelated types.

So keeping foo virtual and returning Ptr<A> in A and Ptr<B> in B is not possible. If you can/are willing to drop virtual than you can use something in the lines of Cem Kalyoncu's proposal or a variation of it.

Comments