Is the following valid? Or how can I get something close to this.
template<class T_> class Template {
//something
};
class Parent {
public:
Template<Parent> variable;
Parent() : variable(this) { }
};
class Derived : public Parent {
public:
Template<Derived> variable;
Derived() : Parent() { }
}
Thanks in advance.
It's technically "valid" in that your compiler has to accept it (it may warn you, and IMHO it should), but it doesn't do what you think it does: Derived's variable is separate from Parent's, and is not getting explicitly initialized (so it uses the default ctor for Template<>).
If you want to have a variable with the same name in a base and derived class you don't need templates.
Just define them and from derived access ->variable and ->Base::variable. Those are 2 different variables.
Few minor types.
But the main problem was that Parent was using a constructor on Template that did not exist.
template<class T>
class Template
{
public:
Template() {} // Used in Derived
Template(T* t) {} // Used in Parent
};
class Parent
{
public:
Template<Parent> variable;
Parent() : variable(this) {}
};
class Derived : public Parent
{
public:
Template<Derived> variable;
Derived() : Parent() {}
};
I am curious what you are trying to achieve though.
Is this some variation of the "Curiously Reoccurring Template" Pattern or something?
You shouldn't get something close to this, because such a redefinition of a public variable violates Liskov Substitution Principle - your Derived becomes more restrictive than Parent, and cannot be substituted in its place, and therefore it shouldn't be in a superclass/subclass relation.
Furthermore, if it would allow you to redefine a field in a sense of actually reusing the same memory location somehow, then it would break the type system as well: all methods in Parent expect variable to be of type Template<Parent>; if it actually be an instance of Template<Derived>, there is no guarantee that Template<T> is covariant in T.
Related
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.
I have the following base template class.
template<typename T>
class Base {
public:
void do_something() {
}
};
It is intended to be used as a curiously recurring template pattern. It should be inherited like class B : public Base<B>. It must not be inherited like class B : public Base<SomeoneElse>. I want to statically enforce this requirement. If someone uses this wrong, I expect an error in the compiling phase.
What I'm doing is putting a static_cast<T const&>(*this) in do_something(). This way the class inheriting the template is or inherits from the class provided as the template parameter. Sorry for the confusing expression. In plain English, it requires B is or inherits from SomeoneElse in class B : public Base<SomeoneElse>.
I don't know if it's the optimal way to achieve this. Looks gross to me.
However I want to do more. I want to ensure B is SomeoneElse itself. How can I do that?
Make the constructor (or destructor) of Base private, and then make T a friend. This way the only thing that can construct/destruct a Base<T> is a T.
If your class contains some code that says:
T* pT = 0;
Base *pB = pT;
Then there will be a compiler error if T is not assignment-compatible with Base.
This kind of check is formalised in C++11 so you don't have to write it by hand and can get helpful error messages:
#include <type_traits>
template<typename T>
class Base {
public:
void do_something()
{
static_assert(
std::is_base_of<Base, T>::value,
"T must be derived from Base");
}
};
class B : public Base<B> { };
int main()
{
B b;
b.do_something();
}
As to ensuring that Base's type parameter is exactly the class that is deriving from it, that seems conceptually flawed. A class that is acting as a base class can't "talk about" the type that is inheriting it. It may be inherited more than once via multiple inheritance, or not at all.
Two good answers so far. Here is another which uses the idiom of generating custom access keys to certain methods (in this case a constructor). It provides an absolute guarantee of correct use while not exposing private methods in the base to the derived.
It can also be used to control access to other methods in the base class on a case-by-case basis.
template<class Derived>
struct Base
{
private:
// make constructor private
Base() = default;
protected:
// This key is protected - so visible only to derived classes
class creation_key{
// declare as friend to the derived class
friend Derived;
// make constructor private - only the Derived may create a key
creation_key() = default;
};
// allow derived class to construct me with a key
Base(creation_key)
{}
// other methods available to the derived class go here
private:
// the rest of this class is private, even to the derived class
// (good encapsulation)
};
struct D1 : Base<D1>
{
// provide the key
D1()
: Base<D1>(creation_key())
{}
};
I have the following structures:
class ElementEx
{
public:
ElementEx() {}
AddChild(ElementEx* element)
{
// some stuff
}
};
class A : ElementEx
{
public:
A() {}
};
class B : ElementEx
{
public:
B() {}
};
template <class T>
class MyNewClass : public T
{
public:
MyNewClass()
{
ElementEx* newElement = new ElementEx();
AddChild(newElement);
}
};
When creating a MyNewClass object, T must inherit from A or B, so MyNewClass will descend from ElementEx. But in my example, the compiler doesn't know this, and can't figure out what AddChild is. How do I make sure the T class is a descendant of ElementEx?
I'm imagining doing
((ElementEx*)this)->AddChild(newElement);
But that seems really inelegant (and prone to error, if the wrong type is fed in as T), and I figure there must be a better way to do this.
The compiler is complaining here because it doesn't know that AddChild is dependent on T during the first pass. AddChild can be made a dependent name by prepending the call with this-> hence delaying the lookup to the second pass when T is known.
As long as you're content that the parent class supports AddChild accepting an ElementEx you can do this easily using the normal compiler error.
After fixing a bunch of errors in your code (A and B inherit privately, all your classes have private constructors, AddChild has no return type) I was able to make it work fine by adding this-> to the call to AddChild because AddChild is a dependent name and you indicate that to the compiler by either qualifying the type or by adding this->. If you don't anticipate the need for virtual calls to that method you could altenately call ElementEx::AddChild to force the correct lookup. Corrected code follows.
class ElementEx
{
public:
ElementEx() {}
void AddChild(ElementEx* element)
{
// some stuff
}
};
class A : public ElementEx
{
public:
A() {}
};
class B : public ElementEx
{
public:
B() {}
};
template <class T>
class MyNewClass : public T
{
public:
MyNewClass()
{
ElementEx* newElement = new ElementEx();
this->AddChild(newElement);
}
};
struct Bad {};
int main()
{
MyNewClass<B> b; // Compiles.
MyNewClass<Bad> bad; // error: 'class MyNewClass<Bad>' has no member named 'AddChild'
}
There are a few ways to do this nicely, but they all have the basis of using 1.) static assert. 2) Static eval functions.
Personaly, I'd use (in the constructor)
static_assert(std::is_base_of<ElementEx,T>::value,"T must derive from ElementEx")
But there is probably a better way. What is the X part of your problem (what are you trying to achieve with this weird inheritance structure?)
I've looked at over a dozen qst's with the phrase no appropriate default constructor available in it but none help with my own problem.
It's a very basic C++ qst (as I'm still learning the ropes), so sorry in advance if your eyes are glazing over at it's simplicity. I am trying to inherit a class that has a templated constructor with no arguments. Such as:
class Base {
public:
template<class T>
Base() {
T *t = this;
//more irrelevant stuff
}
}
I've tried
class Derived : public Base {
public:
Derived() : Base() {
}
}
and
class Derived : public Base {
public:
Derived() {
}
}
to no avail. In both cases I get the error message no appropriate default constructor available . How to go about doing this? If this is not possible can you explain why?
It worked when I set up my constructor like template<class T> Base(T *t) (taking the template argument as a parameter).
p.s. In case it matters, in my code I am also inheriting Derived by another class.
there is no syntax for accessing the default constructor in
class blah_t
{
public:
template< class other_t > blah_t() {}
};
there also some other ways to make the default constructor inaccessible, e.g.
class blah_t
{
public:
blah_t() {}
blah_t( int = 666 ) {}
};
as the holy standard explains it, constructors don't have names…
but, back to the original question, in order to be able to specify the template argument, you need some ordinary function argument that involves the template parameter type
How can I print out the derived class name from the base class without chaining constructors all the way down. In other words is it possible to do this strictly from the base class without adding code in each derived class?
This is an example of what I got, and if there's a way I'd like to get rid of the constructor chaining.
EDIT:
Ideally I am looking for something to add into the base class without having to edit all derived classes. At the moment my real code has got ~17 classes(with need for more), so something that could do the job straight from the base class would be ideal. Even if it's compiler specific (g++ or clang).
#include <iostream>
class Base {
public:
Base(std::string id) {
std::cout<<"Creating "<<id<<std::endl;
}
};
class Child : Base {
public:
Child(std::string id) : Base(id) {}
Child() : Base(typeid(this).name()) {}
};
class GrandChild : Child {
public:
GrandChild(std::string id) : Child(id) {}
GrandChild() : Child(typeid(this).name()) {}
};
class GrandGrandChild : GrandChild {
public:
GrandGrandChild(std::string id) : GrandChild(id) {}
GrandGrandChild() : GrandChild(typeid(this).name()) {}
};
int main() {
GrandGrandChild *A = new GrandGrandChild();
GrandChild *B = new GrandChild();
Child *C = new Child();
return 0;
}
Which prints:
Creating GrandGrandChild
Creating GrandChild
Creating Child
But with compiled added prefix.
There is unfortunately no easy solution.
The problem is that constructing polymorphic objects is quite complicated, at the moment you are building the Base subpart of a Child class, you are building a Base still, not a Child (because trying to access Child members would be non-sensical, they have not been built yet!)
As such, all the ways to retrieve dynamic information (known as RTTI or RunTime Type Information) are voluntarily locked down to prevent such mistake.
For symmetrical reasons, the same occur in the destructor.
Now, only the constructor and destructor are so locked down, therefore you can perfectly have a name() method that will happily return the true name of the dynamic type of the instance in all other cases:
class Base {
public:
std::string name() const { return typeid(*this).name(); }
};
It will work... unless you invoke it from a constructor or destructor in which case it will report the static type.
Now, as far as the "bizarre" output, each implementation (compiler) is allowed to provide its own output here (and they need not even be different for different types, crazy eh!). You seem to be using gcc or clang.
There are demanglers to interpret such output, or if your program is simple enough and their interface scares you, you might simply try to parse it manually to remove the cruft. The name of the class should appear fully, it'll just be preceded with some nonsense (namespaces and numbers essentially).
you can provide an initialization function that needs to be called from each constructor.
class Base {
protected:
Base() { init(typeid(this).name()); }
void init(std::string id) {
std::cout<<"Creating "<<id<<std::endl;
}
};
You somehow need to make sure, that subsequent inits will safely supersede the changes of previous ones:
Creating P4Base
Creating P5Child
Creating P10GrandChild
Creating P15GrandGrandChild
Creating P4Base
Creating P5Child
Creating P10GrandChild
Creating P4Base
Creating P5Child
I intend to use it purely for debugging purposes, which is why something to throw into the base class would be convenient.
have you considered adding a macro to your code to print the debug output?
#ifdef DEBUG
#define PRINT_CLASSNAME std::cout<<"Creating "<<id<<std::endl;
#else
#define PRINT_CLASSNAME ;
#endif
You need to add it to your constructors once, but if you want to disable it (temporarily) you just undefine it?
Since you indicate this is for debugging, you can rely on virtual inheritance to avoid passing the name through all the intermediate derived classes, and instead pass it directly to the Base. Also, Base can be modified to take a template constructor to simplify things for the derived classes.
class Base {
public:
template <typename DERIVED>
Base (DERIVED *d) {
std::cout << "Creating " << typeid(*d).name() << std::endl;
}
};
class Child : virtual public Base {
public:
Child () : Base(this) {}
};
class GrandChild : public Child, virtual public Base {
GrandChild () : Base(this) {}
}
class GrandGrandChild : public GrandChild, virtual public Base {
GrandGrandChild () : Base(this) {}
}