Inheritance of templates - assignement failed - c++

I run into a trouble with templates and inheritance. Consider following code:
#include <iostream>
using namespace std;
class TemplateBase {
public:
TemplateBase() {}
};
class TemplateA: public TemplateBase {
public:
TemplateA():TemplateBase() {}
};
template <class T>
class Base {
public:
Base() {}
};
class Derived: public Base<TemplateA> {
public:
Derived(): Base() {}
};
int main()
{
Base<TemplateBase>* a = new Base<TemplateBase>(); // ok
Base<TemplateA>* b = new Derived(); // ok
Base<TemplateBase>* c = new Derived(); // error: cannot convert ‘Derived*’ to ‘Base<TemplateBase>*’ in initialization
}
The problem is the assignment of pointer c, which fails from unknown reason for me. I am trying to assign the Derived<AnotherDerived> to Base<AnotherBase>, is this possible?
Thank you for any help.

Your Derived is a non-template class derived from Base<TemplateA>. In the line
Base<TemplateBase>* c = new Derived();
you are trying to refer to a Derived object via a pointer to Base<TemplateBase>. For the compiler, there is no relation between Base<TemplateBase> and Derived, hence it fails. The only possible base to use is Base<TemplateA> from which Derived is derived.
A possible solution is to templatize the Derived, like
template<typename T>
class Derived: public Base<T> {
public:
Derived(): Base<T>() {}
};
then use as
Base<TemplateBase>* c = new Derived<TemplateBase>;
See a live example here.

vsoftco gives a good outline of why this is invalid. An example of why this is the case in C++ is that although TemplateBase and TemplateA are related, Base<TemplateBase> and Base<TemplateA> are completely different. We could even specialize Base in a way which makes them have an incompatible interface:
template<>
struct Base<TemplateBase>
{
Base() = delete;
Base(int i) {}
}
Now it's obvious that Base<TemplateBase> and Base<TemplateA> can't be used in the same way, because one is default-constructable and one isn't. As such, it's impossible to use them polymorphically, because the compiler won't know what code to generate.

Polymorphism says a base class pointer can point to a derived class object.
But the same can't happen for templates.
Since Polymorphism is a dynamic feature and bound at run-time.
Templates are a static feature and bound at the compile time.

You make a common mistake, you think that relation between classes:
class A {};
class B : public A {};
Will propagate this relation to templates:
template <class T>
class Tmpl {};
Tmpl<A> a; Tmpl<B> b;
a = b; // fails!
So you expected that Tmpl<A> would be a parent to Tmpl<B> but that is not the case. To simulate that you would need to make a constructor, that allows such conversion:
template <class T>
class Tmpl {
T data;
public:
Tmpl() : data() {}
template<class Parent>
Tmpl( const Tmpl<Parent> &t ) : data( t.data ) {}
};
Tmpl<A> a; Tmpl<B> b;
a = b; // works!
For details you should look into smart pointer implementation, there is similar problem there - assignment from pointer to child from base needs to work.

The Derived class is derived from Base<TemplateA> so Base<TemplateBase>* c = new Derived() is equivalent to saying
Base<TemplateBase>* c = new Base<TemplateA>() which is incorrect because Base<TemplateA> is a different class altogether.
TemplateBase is a base class for TemplateA but same does not hold true for Base<TemplateBase> and Base<TemplateA>.

Related

Example of useful downcast with static_cast which does not produce undefined behaviour

I am wondering about a short code example of an application of downcast via static_cast, under conditions where there is no undefined behaviour.
I have looked around and I found quite a few texts (posts, Q&A, etc.) referring to fragments of the standard, explaining, etc.
But I found no examples that illustrate that (and that surprises me).
Could anyone provide one such example?
A downcast via static_cast is part of the typical implementation of the Curiously recurring template pattern (CRTP). The example from wikipedia:
template <class T>
struct Base
{
void interface()
{
// ...
static_cast<T*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
T::static_sub_func();
// ...
}
};
struct Derived : Base<Derived>
{
void implementation();
static void static_sub_func();
};
Base "knows" that it can downcast this to T* via static_cast (rather than dynamic_cast) because the whole purpose of Base is to be inherited by T. For more details on CRTP I refer you to the wikipedia article.
A very basic example:
class Animal {};
class Dog : public Animal {};
void doSomething() {
Animal *a = new Dog();
Dog *d = static_cast<Dog*>(a);
}
A more contrived example:
class A { public: int a; };
class B : public A {};
class C : public A {};
class D : public B, public C {};
void doSomething() {
D *d = new D();
int bValue = static_cast<B*>(d)->a;
int cValue = static_cast<C*>(d)->a;
// This does not work because we have two a members in D!
// int eitherValue = d->a;
}
There are also countless other cases where you know the actual type type of the instance due to some flags or invariants in your program. However, many sources recommend preferring dynamic_cast in all cases to avoid errors.

Is there a way to forbid a base class method call in the derived class?

In c++ "protected" modifier allow method calls only in derived classes. Is it possible to implement inverse logic - prohibit calling a base class method in the derived classes? The code below illustrates what I want to get.
class Base
{
int data;
protected:
// This constructor should be called only in the derived classes
Base(int d): data(d) { }
public:
// This construcor can be called wherever except a derived classes!
Base(): data(0) { }
};
class Derived : public Base
{
public:
// The developer must not forget to initialize "data"
Derived() : Base(10) {}
// I want to get a compilation error there
Derived() : Base() {}
};
Is it possible to [...] prohibit calling a base class method in the derived classes?
Yes. By using private access specifier. Private names are accessible only to the class itself.
It is not inverse logic however. It is not possible for reduce accessibility of of otherwise public name from derived classes.
// This construcor can be called wherever except a derived classes!
There is no way to do this. A public function can be called by anyone and there is no SFINAE trick you can use to stop it if it is called by a derived class since the constructor has no idea where it is called from.
This seems like a XY problem. Although I do not recommend this (I recommend rethinking the design) I found (for better or worse) a solution inspired from the CRTP pattern:
template <class D = void>
class Base
{
protected:
int data;
protected:
// This constructor should be called only in the derived classes
template <class Der = D, class = std::enable_if_t<std::is_base_of_v<Base, Der>>>
Base(int d): data(d) {}
public:
// This constructor can be called wherever except a derived classes!
template <class Der = D, class = std::enable_if_t<!std::is_base_of_v<Base, Der>>>
Base(): data(0) { }
};
class Derived : public Base<Derived>
{
int mydata = 1;
public:
// The developer must not forget to initialize "data"
Derived() : Base(24) {}
// I want to get a compilation error there
//Derived() : Base() {} // (1) compilation error here
};
auto test()
{
Base b1{};
//Base b2{24}; // (2) compilation error here
Derived d{};
}
Of course there are problems with this. For starters there is nothing stopping from creating a derived class as class Derived : public Base<void>.
And if you want, you can add a common base class
class Base_l0
{
};
template <class D = void>
class Base_l1 : Base_l0
{
};
class Derived : public Base_l1<Derived>
{
};
The short answer is no.
In C++, there is only public protected and private. There is no middle ground. Your functions are either accessible from everywhere (public), from nowhere except the class itself (private), or from the class and its children (protected).
I only want to force the user to perform some additional actions wlile inheritting [sic]. For example, to avoid random errors.
If calling the default constructor causes errors by calling it while inheriting from it, then then it is probable it causes errors when you are not inheriting from it. That means you probably shouldn't have this constructor as public anyway, if at all.

Check if constructors of subclass are public in C++

Hope this is not duplicated, but wasn't able to find an elegant solution. Is it possible to say that subclasses of a special base class can only created in a template factory function? Because of simplicity I only want to force this behavior in the base class. Here is an simple example:
template <class T>
T* createBase();
template<typename T>
class Base {
protected:
template <class T>
friend T* createBase();
static T* create()
{
return new T();
}
};
class TestClass1 : public Base<TestClass1>
{
public:
TestClass1() : Base() {}
};
template <class T>
T* createBase()
{
static_assert(std::is_base_of<Base<T>, T>::value, "use the createBase function only for Base<T> subclasses");
return Base<T>::create();
}
Actually this is allowed:
TestClass2 *testClass = createBase<TestClass2>();
TestClass2 tester;
But I only want to have this:
TestClass1 *testClass = createBase<TestClass1>(); //allowed
TestClass1 tester; // compile error
For sure I know I only have to put the constructor of TestClass1 private or protected. But it would be really nice to say that in the Base object.
Edit:
An compile error when the constructor of the subclass is public would be a also a nice solution. Maybe with a static_assert().
You can't control the accessibility of a constructor from the base class, even with CRTP.
What you can do is add a static_assert in the base ctor checking that the T a.k.a the derived class has no publicly accessible default ctor:
template <class T>
class Base {
public:
Base() {
static_assert(!std::is_default_constructible<T>::value,
"T must not be default constructible");
}
};
the static_asswert doesn't work on class scope for reasons showned here: CRTP std::is_default_constructible not working as expected

Derived curiously recurring templates and covariance

Suppose I have a base class which cloning of derived classes:
class Base
{
public:
virtual Base * clone()
{
return new Base();
}
// ...
};
I have a set of derived classes which are implemented using a curiously recurring template pattern:
template <class T>
class CRTP : public Base
{
public:
virtual T * clone()
{
return new T();
}
// ...
};
And I attempt to derive from that further like this:
class Derived : public CRTP<Derived>
{
public:
// ...
};
I get compilation errors to the effect of:
error C2555: 'CRTP<T>::clone': overriding virtual function return type differs and is not covariant from 'Base::clone'
I realize this is probably a result of the compiler not fully knowing the inheritance tree for Derived when instantiating CRTP. Furthermore, replacing the return type (T*) with (Base*) also compiles. However, I would like to know if there is a work around which retains the above semantics.
A not-so-pretty workaround.
class Base
{
protected:
virtual Base * clone_p()
{
return new Base();
}
};
template <class T>
class CRTP : public Base
{
protected:
virtual CRTP* clone_p()
{
return new T;
}
public:
T* clone()
{
CRTP* res = clone_p();
return static_cast<T*>(res);
}
};
class Derived : public CRTP<Derived>
{
public:
};
Use dynamic_cast<> instead of static if you feel it's safer.
If you can live with having to use a different syntax for specifying complete types, you might do the following (warning: untested code):
Let's first start with the machinery:
// this gives the complete type which needs to be used to create objects
// and provides the implementation of clone()
template<typename T> class Cloneable:
public T
{
public:
template<typename... U> Cloneable(U&&... u): T(std::forward<U>(u) ...) {}
T* clone() { return new Cloneable(*this); }
private:
// this makes the class complete
// Note: T:: to make it type dependent, so it can be found despite not yet defined
typename T::CloneableBase::CloneableKey unlock() {}
};
// this provides the clone function prototype and also makes sure that only
// Cloneable<T> can be instantiated
class CloneableBase
{
template<typename T> friend class Cloneable;
// this type is only accessible to Clonerable instances
struct CloneableKey {};
// this has to be implemented to complete the class; only Cloneable instances can do that
virtual CloneableKey unlock() = 0;
public:
virtual CloneableBase* clone() = 0;
virtual ~CloneableBase() {}
};
OK, now the actual class hierarchy. That one is pretty standard; no CRTP intermediates or other complications. However no class implements the clone function, but all inherit the declaration (directly or indirectly) from CloneableBase.
// Base inherits clone() from CloneableBase
class Base:
public CloneableBase
{
// ...
};
// Derived can inherit normally from Base, nothing special here
class Derived:
public Base
{
// ...
};
Here's how you then create objects:
// However, to create new instances, we actually need to use Cloneable<Derived>
Cloneable<Derived> someObject;
Derived* ptr = new Cloneable<Derived>(whatever);
// Now we clone the objects
Derived* clone1 = someObject.clone();
Derived* clone2 = ptr->clone();
// we can get rid og the objects the usual way:
delete ptr;
delete clone1;
delete clone2;
Note that a Cloneable<Derived> is-a Derived (it is a subclass), therefore you need to use Cloneable only for construction, and can otherwise pretend to work with Derived objects (well, tyepinfo will also identify it as Cloneable<Derived>).

How to define sealed class in C++?

How to stop the class to be inherited by other class.
C++11 solution
In C++11, you can seal a class by using final keyword in the definition as:
class A final //note final keyword is used after the class name
{
//...
};
class B : public A //error - because class A is marked final (sealed).
{ // so A cannot be derived from.
//...
};
To know the other uses of final, see my answer here:
What is the purpose of the "final" keyword in C++11 for functions?
C++03 solution
Bjarne Stroustrup's code : Can I stop people deriving from my class?
class Usable;
class Usable_lock {
friend class Usable;
private:
Usable_lock() {}
Usable_lock(const Usable_lock&) {}
};
class Usable : public virtual Usable_lock {
public:
Usable();
Usable(char*);
};
Usable a;
class DD : public Usable { };
DD dd; // error: DD::DD() cannot access
// Usable_lock::Usable_lock(): private member
Generic_lock
So we can make use of template to make the Usable_lock generic enough to seal any class:
template<class T>
class Generic_lock
{
friend T;
Generic_lock() {} //private
Generic_lock(const Generic_lock&) {} //private
};
class Usable : public virtual Generic_lock<Usable>
{
public:
Usable() {}
};
Usable a; //Okay
class DD : public Usable { };
DD dd; //Not okay!
There are two ways, the simple cheap, and the correct one. The two answers by #Naveen and #Nawaz deal with the correct one, that requires manual creation of a sealer class for each class that you actually want to seal.
The not fool-proof way, which is used in the adobe libraries is using a templated class for that. The problem is that you cannot declare the template argument as a friend, and that means that you will have to switch from private to the less safe protected:
template <typename T>
class sealer {
protected: sealer() {}
};
class sealed : virtual sealer<sealed> {};
And you can automate it with a macro (I don't remember the exact flavor of the macro in Adobe's code):
#define seal( x ) virtual sealer<x>
class sealed : seal(sealed)
{};
Now this will catch people that mistakenly try to inherit without knowing that they shouldn't:
class derived : sealed {};
int main() {
derived d; // sealer<T>::sealer() is protected within this context
}
But it will not inhibit people that really want to from deriving, as they can gain access to the constructor by deriving from the template themselves:
class derived : sealed, sealer<sealed> {};
int main() {
derived d;
};
I am not sure whether this will change in C++0x, I think I recall some discussions on whether a class template would be allowed to befriend one of it's arguments, but in a cursory search through the draft I cannot really tell. If that was allowed then this would be a fine generic solution:
template <typename T>
class sealer {
sealer() {}
friend class T; // Incorrect in C++03
};
C++11 adds the ability to prevent inheriting from classes or simply preventing overriding methods in derived classes. This is done with the special identifier final. For example:
class Base final { };
class Derived1 : Base { }; // ill-formed because the class Base has been marked final
or
class Base {
virtual void f() final;
};
class Derived : Base {
void f(); // ill-formed because the virtual function Base::f has been marked final
Note that final is not a language keyword. It is technically an identifier; it only gains special meaning when used in those specific contexts. In any other location, it can be a valid identifier.
Based on Bjarne Stroustrup's http://www.stroustrup.com/bs_faq2.html#no-derivation FAQ
with small modification without friend keyword usage:
// SEALED CLASS DEFINITIONS
class Usable_lock {
protected:
Usable_lock() {}
Usable_lock(const Usable_lock&) {}
};
#define sealed_class private virtual Usable_lock
// SEALED CLASS USAGE EXMAPLES
class UsableLast : sealed_class {
public:
UsableLast(){}
UsableLast(char*){}
};
class DD : public UsableLast {};
// TEST CODE
template <class T> T createInstance() {
return T();
}
int main()
{
createInstance<UsableLast>();
// createInstance<DD>();
return 0;
}
The following code shows how to define a sealed class in C++/CLI.
class A sealed
{
//here goes the class code
};
class B : public A
{
};
Now B : cannot inherit from A as it has been declared as 'sealed'. Also a detailed explanation about sealed keyword can be found here http://msdn.microsoft.com/en-us/library/0w2w91tf.aspx
Update: Added C++/CLI , also other answers have shown the latest C++11 way of achieving the same using final keyword.
You cannot. C++ is not Java or C#. And also there is no point, ever, IMHO.