C++ how to implement conditional inheritance with the following example - c++

What I want to doe is a simple conditional inheritance in the Foo class
so depending on how it's instanciated (see usage)
class BaseType
{
protected:
m_valueX;
public: BaseType(int param = 0):m_valueX(param){}
~ BaseType(){}
}
...
class Type1 : public BaseType
{
public: Type1():BaseType(1){}
~Type1(){}
}
...
class Type2 : public BaseType
{
public: Type2(): BaseType(2){}
~Type1(){}
}
...
template<typename Base>
class Foo: public Base
{
public:
Foo(){}
~Foo();
void dothis();
}
...........
in cpp file
template<typname Base>
Foo<Base>::Foo():Base()
{
}
Foo::~Foo(){}
void Foo::dothis(){}
usage:
Foo* fooptr1 = new Foo<Type1>();<== error use of class template requires template argument list
Foo* fooptr2 = new Foo<Type2>();>();<== error use of class template requires template argument list
Thank you!

Foo is a template, not a class. The common class type for all Foo<T> is Base, so you can say:
Base * p1 = new Foo<Type1>;
Base * p2 = new Foo<Type2>;

Related

c++ covariant constructions with respect to template parameters

I have a base class and its derived class with pointers to forward declared classes:
class BaseParam;
template <class S = BaseParam> class Base;
class BaseParam {
private:
std::unique_ptr<Base<>> ptr;
public:
virtual const Base<>& get_ptr() const {return *ptr;}
};
And similarly for its derived class
class DerivedParam;
template <class S = DerivedParam> class Derived;
class DerivedParam : public BaseParam {
private:
std::unique_ptr<Derived<>> ptr;
public:
const Derived<>& get_ptr() const override {return *ptr;} // <---- Here we'll have trouble
};
The above mentioned class templates are also intertwined with the Param versions, here's the prototype:
template <class S>
class Base {
private:
std::unique_ptr<S> ptr;
// ...
public:
// ...
const S& get_ptr() const { return *ptr; }
};
template <class S>
class Derived : public Base<S> {
};
So that Derived = Derived<DerivedParam> inherits from Base<DerivedParam> But in order to make the return marked with <-- above covariant, we would need Derived to inherit from Base = Base<BaseParam>. How does one do this in a clean fashion? I cannot add an extra inheritance say like
template <class S>
class Derived: public Base<S>, public virtual Base<>
Cause Base and Base<DerivedParam> will hold two different pointers to BaseParam and to DerivedParam. Since a pointer to DerivedParam decays to one to BaseParam there should be a solution where the base class holds only one pointer.
So what I am asking is if there is some functorial way of defining class inheritance for class templates.

Template class on a abstract class

So I have a class template Foo:
template <typename T>
class Foo
{
public:
Foo();
~Foo();
//...
};
I have two derived classes from the Foo class:
class FooDerived1 : public Foo<int>
{
public:
FooDerived1 ();
~FooDerived1 ();
};
class FooDerived2 : public Foo<double>
{
public:
FooDerived2 ();
~FooDerived2 ();
};
But now I saw that the class template was being used on a abstract class IBar like this:
class Foo;
class IBar
{
public:
virtual void placeFoo(Foo& foo) = 0; //error
virtual void removeFoo(Foo& foo) = 0;
};
I know I cannot use templates classes in abstract virtual classes.
But..in a case like this, what should I do?
I really need the IBar abstract class like this...
Forget the usage of template classes?
Option 1: Make IBar itself a template class.
template <class T>
class Foo;
template <class T>
class IBar
{
public:
virtual void placeFoo(Foo<T>& foo) = 0;
virtual void removeFoo(Foo<T>& foo) = 0;
};
Option 2: Make all Foo<T> derive from a common, non-generic FooBase.
class FooBase
{
// ...
};
template <typename T>
class Foo : public FooBase
{
public:
Foo();
~Foo();
//...
};
// ...
class FooBase;
class IBar
{
public:
virtual void placeFoo(FooBase& foo) = 0;
virtual void removeFoo(FooBase& foo) = 0;
};
The viability of both solutions depends on how much you actually depend on the T type. But that's what you should expect when you mix virtual functions with templates. With option 1, you do not have a common interface type anymore; with option 2, FooBase cannot provide any member function with a T-dependent argument.
By the way, don't forget about virtual destructors in your real code.
If you need common behaviour, create base class for all instances of Foo<>:
class FooBase
{
//common interface and data
};
template <class T>
class Foo : public FooBase
{
};
And then:
class FooBase;
class IBar
{
public:
virtual void placeFoo(FooBase& foo) = 0; //ok
virtual void removeFoo(FooBase& foo) = 0;
};
The thing is, that you try to mix templates (compile time) and dynamic polymorphism (runtime), which can be problematic (is it what you meant by "I know I cannot use templates classes in abstract virtual classes"?).
Why not stick to using templates?
class IBar
{
public:
template <class T>
void placeFoo(Foo<T>& foo);
template <class T>
void removeFoo(Foo<T>& foo);
};
or:
template <class T>
class IBar
{
public:
void placeFoo(Foo<T>& foo);
void removeFoo(Foo<T>& foo);
};

Templated class unknown type over multiple layers

I've got following class Foo and FooBase:
class FooBase
{
public:
virtual void A() = 0;
};
template <class T>
class Foo : public FooBase
{
public:
virtual void A() {}
private:
T mT;
};
FooBase is here to have a instance without needing to know the type, so I can do s.th. like this:
FooBase *foo = new Foo<int>();
Pretty standard. Now the issue: I want to bring the same thing to the next level.
So I've got the class:
template <class T>
class Bar : public Foo<T>
{
public:
virtual void B() {}
};
And can of course use:
Bar<int> *bar = new Bar<int>();
Except I don't know the type of the template class.
So initial idea was to do the following:
class BarBase : public FooBase
{
public:
virtual void B() {}
};
template <class T>
class Bar : public BarBase, Foo<T>
{
};
So I can do the following:
BarBase *bar = new Bar<int>();
For obvious reasons this doesn't work - the question is now: How to get s.th. like this to work?
You can solve this issue with virtual inheritance. This feature assures that there is only one instance of your virtually-inherited base class when you instantiate a subclass. For your example, this would look like:
class FooBase
{
public:
virtual void A() = 0;
};
template <class T>
class Foo : public virtual FooBase
// ^^
{
public:
virtual void A() {}
private:
T mT;
};
class BarBase : public virtual FooBase
// ^^
{
public:
virtual void B() {}
};
template <class T>
class Bar : public BarBase, Foo<T>
{
};
Now you can happily create instances like you wanted:
BarBase *bar = new Bar<int>();

Create object of class inherited from type provided by different object

I have the following classes
class CommonStyle
{};
class Style1 : public CommonStyle
{};
class Style2 : public CommonStyle
{};
class Style3 : public CommonStyle
{};
template<typename T> class ZStyle : public T
{
};
I have object which can be type of Style1, Style2, Style3.
How can I create object of ZStyle inherited from Style1 or Style2 or Style3 depend on provided object?
//pseudo-code
int _tmain(int argc, _TCHAR* argv[])
{
CommonStyle* obj1 = new Style1();
CommonStyle* obj2 = new Style2();
CommonStyle* obj3 = new Style3();
ZStyle* zobj1 = create_object_inherited_from_style1(obj1);
ZStyle* zobj2 = create_object_inherited_from_style2(obj2);
ZStyle* zobj3 = create_object_inherited_from_style3(obj3);
}
Is it possible to avoid dynamic_cast?
I might be answering a different question, but it may be the solution to you problem.
The virtual constructor idiom may be helpful.
You create a virtual method called clone() in the base class, which is overridden in descendant classes. Then, you write
CommonStyle* zobj1 = obj1.clone();
CommonStyle* zobj2 = obj2.clone();
CommonStyle* zobj3 = obj3.clone();
This results in three objects with static type CommonStyle, but dynamic type depending on what object they were clone()'d from.
How about the following CRTP-like modification:
template<typename T> class ZStyle : public T
{
ZStyle(T const &);
};
class CommonBase
{
/* original CommonStyle in here */
virtual CommonBase * z() const = 0;
}
template<typename T> class CommonStyle : public CommonBase
{
virtual ZStyle<T> * z() const
{
return new ZStyle<T>(static_cast<T const&>(*this));
}
};
class Style1 : public CommonStyle<Style1> { };
class Style2 : public CommonStyle<Style2> { };
class Style3 : public CommonStyle<Style3> { };
Usage:
CommonStyle* obj1 = new Style1();
ZStyle<Style1> * p = obj1.z();
Alternatively, you can make the return type of z() to be CommonBase * so you don't need to worry about the type dependence in the last line.

C++ templates with interface objects

I have the following code that doesn't 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 won't compile because g is a different type than Group<Derived>. To make this work in Java I would do something such as Group<? extends Base> g, but C++ doesn't have that keyword as far as I know. What can be done?
Edit: I would like to clarify that I do not want it possible to set types not derived from Base as g. I have updated my example to explain this.
Edit 2: There are two solutions to my problem. Dave's I found to be simple and easy to define. But Bowie's (along with Mark's additions) suited my needs better.
The classes Group<Base> and Group<Derived> are entirely unrelated, different classes. Pointers to them are not convertible in either direction.
If you need runtime-polymorphic behaviour, your class template Group could derive from a common (non-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>;
You could make Group< Base > a base class of 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
}
Bowie Owens's Answer handles the covariance you need to solve the original question. As for the constraint you asked for in the edited question - you can achieve this by using type traits.
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 { };
I don't think C++ support that. C++ Template is handled completely at compile time so it doesn't support polymorphism. That means the type of the template arguments should be exactly the same for both side of the assignment expression.
I think I understand what you're going for. I'm not sure it's the best approach (and you might want to 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
}