Since the question comes from someone with a Java background, I will interpret it in Java terms. You want to define a generic interface that will return an object derived from T:
template<typename T>
struct getter
{
virtual T* get() = 0; // just for the signature, no implementation
};
Note the changes: the function is declared virtual so that it will behave polimorphically in derived objects. The return value is a pointer instead of an object. If you keep an object in your interface, the compiler will slice (cut the non-base part of the returned object) the return. With some metaprogramming magic (or resorting to boost) you can have the compiler test the constraint that T derives from a given type.
Now the question is why you would like to do so... If you define a non-generic interface (abstract class) that returns a Thing by pointer you can just get the same semantics more easily:
struct Thing {};
struct AnotherThing : public Thing {};
struct getter
{
virtual Thing* get() = 0;
};
struct AnotherGetter : public getter
{
virtual AnotherThing* get() { return 0; }
};
struct Error : public getter
{
int get() { return 0; } // error conflicting return type for get()
};
struct AnotherError : public getter
{
};
int main() {
AnotherError e; // error, AnotherError is abstract (get is still pure virtual at this level)
}
The compiler will require all instantiable classes derived from getter to implement a get() method that returns a Thing by pointer (or a covariant return type: pointer to a class derived from Thing). If the derived class tries to return another type the compiler will flag it as an error.
The problem, as you post it is that if you use the interface, then the objects can only be handled as pointers to the base Thing class. Now, whether that is a problem or not is another question... In general, if you have correctly designed your hierarchy, you should be able to use the returned objects polimorphically without having to resort to down casting.
Note that if you are using the different getters at the most derived level in the hierarchy, each get()
method returns the most derived element from the Thing hierarchy, at that point you will not need to down cast at all. Only if you use the different getters through the base getter
interface you will get the same return type for all (Thing*
)
It is important to note that templates are resolved completely at compile time. That means that trying to use templates to solve the need (do you really need it?) to downcast will not help you if you use the different getters through the interface (reference/pointers to the basic getter).
Maybe posting a little more details on your specific domain, where and how you intend to use this code, can help in providing more useful responses.