C ++ templates with interface objects

I have the following code that does not compile.

class Base { public: virtual ~Base() { }; }; class Derived : public Base { }; class NotDerived { }; template <typename T> class Group { }; int main() { Group<Base> *g = NULL; g = new Group<Base>(); // Works g = new Group<Derived>(); // Error, but I want it to work g = new Group<NotDerived>(); // Error, as expected } 

I understand that this does not compile because g is a different type than Group<Derived> . To make this work in Java, I would do something like Group<? extends Base> g Group<? extends Base> g , but C ++ does not have this keyword as far as I know. What can be done?

Edit: I would like to clarify that I do not want to be able to set types not derived from Base , like g . I updated my example to explain this.

Edit 2: There are two problems with my problem. Dave's I found it simple and easy to spot. But Bowie's (along with Mark's add-ons) were better suited to my needs.

+7
source share
6 answers

You can make Group <Base> a base class for all Group <T> T! = Base.

 class Base { public: virtual ~Base() { }; }; class Derived : public Base { }; template <typename T> class Group; struct Empty { }; template <typename T> struct base_for_group_t { typedef Group<Base> type; }; template <> struct base_for_group_t<Base> { typedef Empty type; }; template <typename T> class Group : public base_for_group_t<T>::type { }; int main() { Group<Base> *g = 0; g = new Group<Base>(); // Works g = new Group<Derived>(); // now works } 
+3
source

Classes Group<Base> and Group<Derived> completely unrelated, different classes. Pointers to them are not converted in any direction.

If you require polymorphic runtime behavior, your Group template template can be obtained from a common (not templated) base class:

 class Group // base { virtual ~Group() { } }; template <typename T> class ConcreteGroup : public Group { // ... T * m_impl; }; Group * g1 = new ConcreteGroup<A>; Group * g1 = new ConcreteGroup<B>; 
+5
source

Comment Bowie Owens handles the covariance needed to resolve the original question. Regarding the restriction that you asked in the editable question, you can achieve this by using type properties.

 template <typename T, class Enable = void> class Group; template <typename T> class Group<T, typename enable_if<is_base_of<Base, T>::value>::type> : public base_for_group_t<T>::type { }; 
+2
source

I do not think this supports C ++. The C ++ template is fully processed at compile time, so it does not support polymorphism . This means that the type of template arguments must be exactly the same for both sides of the assignment expression.

+1
source

C ++ templates and java generics are very different, for example, a square and a circle. one generates code, the other checks to see if types and matches will work at runtime in a common code block. in very short words.

What are the differences between the "generic" types in C ++ and Java?

0
source

I think I understand what you're going for. I'm not sure if this is the best approach (and you can take a look at Boost.Factory ).

 template <class T> class Factory { public: virtual T* operator()() = 0; }; template <class Derived, class Base> class ConcreteFactory : public Factory<Base> { public: virtual Base* operator()() { return new Derived(); } }; class Base { public: virtual ~Base() {}; }; class Derived1 : public Base { }; class Derived2: public Base {}; class NotDerived {}; int main() { Factory<Base>* g; g = new ConcreteFactory<Derived1, Base>; g = new ConcreteFactory<Derived2, Base>; // g = new ConcreteFactory<NotDerived, Base>; // Will not work if you try to do this } 
0
source

All Articles