[C++] Konkretyzacja szablonów

Witam. Jakie typy danych w podanym szablonie dopuści kompilator i dlaczego?

#include 


class X {};

class Y : public X {};


template

class A {

public: 

	A() {}

public: 

	virtual T b(T x) = 0;

};


template

class B : public A {

public: 

	X b(T x) { return x; };

};


int main(void) {

	B<???> x;

	x.b(/*co tutaj?*/);

	return 0;

}

Jakie typy dopuści to zależy od tego, jakich operatorów i metod używasz. Podczas kompilacji kompilator utworzy nowe klasy podmieniając szablon na daną klasę i próbuję skompilować, dlatego też klasy szablonowe muszą być w jednym pliku kompilowanym razem z użyciem tej klasy.

Wydaje mi się że dopuści tam akurat wszystko, co da się zrzutować do X (np. klasa X i Y, w tym przypadku).

U mnie (g++ 4.7) B działa bez problemu, ale próba użycia B kończy się na:

test_cpp.cpp: In instantiation of ‘class B’:

test_cpp.cpp:21:10: required from here

test_cpp.cpp:17:6: error: invalid covariant return type for ‘X B::b(T) [with T = Y]’

test_cpp.cpp:11:15: error: overriding ‘T A::b(T) [with T = Y]’

Wniosek: typ zwracany przez przeciążoną metodę musi być dokładnie taki sam jak metody bazowej. Ale jak się już stworzy obiekt klasy B, to do metody b można przekazać argument dowolnego typu, na podstawie którego da się stworzyć obiekty klasy X. Specjalnie nie mówię o rzutowaniu, bo coś takiego też działa:

class X {

public:

    X() {}

    X(int) {}

};


template

class A {

public:

    A() {}

    virtual T b(T x) = 0;

};


template

class B : public A {

public:

   X b(T x) { return x; };

};


int main() {

    B b;

    b.b(5);

    return 0;

}