Copy constructor for every derived class - c++

Consider the following code. I want the convert function to work without defining the T(const Base&) copy constructor in every concrete derived type of Base.
It could be done in the intermediate class CRTP<T> in the way illustrated only if it is not abstract, but it is abstract. So how can I make it work in this case?
struct Base {
virtual void foo() = 0;
};
template <typename T>
struct CRTP : virtual Base {
CRTP (const Base& base) : Base(base) { }
CRTP() = default;
// virtual void foo() override { } // CRTP<T> is abstract.
};
struct Derived1 : CRTP<Derived1> {
Derived1 (const Base& base) : Base(base) { }
Derived1() = default;
virtual void foo() override { }
};
struct Derived2 : CRTP<Derived1> {
Derived2 (const Base& base) : Base(base) { }
Derived2() = default;
virtual void foo() override { }
};
template <typename T, typename U>
T* convert (const U& u) {
// return new T(u); // This works, but only if T(const Base&) constructor is defined in every Base concrete derived type.
return dynamic_cast<T*>(new CRTP<T>(u)); // This only works if CRTP<T> is not abstract.
}
int main() {
Derived1 d1;
Derived2* d = convert<Derived2, Derived1>(d1);
}

But, as a matter of fact, it is not a copy constructer, so it could be simply delegated like this:
struct Derived1 : CRTP<Derived1> {
using CRTP<Derived1>::CRTP;
Derived1() = default;
virtual void foo() override {
}
};
You can also use a pointer instead of a reference, which seems more relevant in your code by the way, because convert() returns a pointer. Such constructor is not considered as a copy constructor and can always be delegated to the children.

Related

How to call virtual functions of a derived class through base class pointers, assuming functions in base class are not virtual

class Base
{
public:
virtual void f()
{
g();
}
virtual void g()
{
cout<<"base";
}
};
class Derived : public Base
{
public:
virtual void f()
{
Base::f();
}
virtual void g()
{
cout<<"derived";
}
};
int main()
{
Base *pBase = new Derived;
pBase->f();
return 0;
}
In this program I have kept both derived and base class functions as virtual. Is it possible call virtual functions of derived class through base class pointer and base class functions are not virtual.
Thanks in advance..
assuming functions in base class are not virtual
This can be achieved via type erasure. But there are caveats.
Your "base" class should decide between the two:
Being a view class (can't be called delete on or created by itself)
Being a resource owning class (implemented similar to 1, but stores a smart pointer).
Here is an example for case 1: https://godbolt.org/z/v5rTv3ac7
template <typename>
struct tag{};
class base
{
public:
base() = delete;
template <typename Derived>
explicit base(tag<Derived> t)
: _vTable(make_v_table(t))
{}
int foo() const { return _vTable.foo(*this); }
protected:
~base() = default;
private:
struct v_table
{
virtual int foo(const base &b) const = 0;
protected:
~v_table() = default;
};
template <typename Derived>
static const v_table& make_v_table(tag<Derived>){
struct : v_table
{
int foo(const base &b) const {
return static_cast<const Derived&>(b).foo();
}
} static const _vTable{};
return _vTable;
}
private:
const v_table& _vTable;
};
class derived : public base
{
public:
explicit derived()
: base(tag<derived>{})
{}
int foo() const { return 815; }
};
// example
#include <iostream>
int main(){
derived d{};
const base& b = d;
std::cout << b.foo() << '\n';
}
Take notice, that you can only take a pointer or a reference (cv-qualified) to a base class. The base class can't be created on its own.
Also tag<T> is needed to call a templated constructor.
DO NOT CALL DERIVED METHODS IN THE BASE CONSTRUCTOR OR DESTRUCTOR
Simple answer is no, if the function you are calling is not virtual. The Compiler would have no Idea that you are trying to call a function from the Derived Class, and won't make and I'm paraphrasing here since I do not know the proper term for,"Won't make proper entries in the Virtual Table".
class Base
{
public:
void f()
{
std::cout<<"Base f() Called\n";
g();
}
virtual void g()
{
std::cout<<"Base g()\n";
}
virtual ~Base(){std::cout<<"Base Destroyed\n";}
};
class Derived : public Base
{
public:
void f()
{
g();
}
virtual void g()
{
std::cout<<"Derived g()\n";
}
~Derived(){std::cout<<"Derived Destroyed\n";}
};
int main()
{
Derived* D1 = new Derived();
Base* B1 = D1;
B1->f();
delete B1;
return 0;
}
Have a look at the following code, I have not declared Base::f() as virtual,calling B1->f() calls the Base Method, but the base method calls a virtual function Base::g() and this allows the "Derived" method be called.
Have a look at this thread or this blogpost to understand Virtual Tables.
(1) and you must ALWAYS declare the destructor of a base class virtual when destroying Derived Object through a Base Pointer, else the resources used by the Derived Object will never get destroyed and it's memory will leak until the program closes.
Don't Take my word as gospel, I am simply passing on knowledge I have acquired from first hand experience, Except for (1), specially if you are not using smart pointers

How to copy derived classes when we dont know which classes are? [duplicate]

The typical pattern when you want to copy a polymorphic class is adding a virtual clone method and implement it in each derived class like this:
Base* Derived::clone()
{
return new Derived(*this);
}
Then in a calling code you can:
Base *x = new Derived();
Base *y = x->clone();
However if you have 50+ derived classes and realize you need polymorphic copy, it's tedious to copy-paste the cloning method into each of them. And it's essentially a boilerplate that works around a language limitation that you have to spell out the actual name to call the constructor.
I haven't keep track with the new features in recent C++ standards... Is there a way to avoid this in modern C++?
You can use this generic CRTP code
template <class Derived, class Base>
struct Clonable : Base {
virtual Base* do_clone() {
return new Derived(*static_cast<Derived*>(this));
}
Derived* clone() { // not virtual
return static_cast<Derived*>(do_clone());
}
using Base::Base;
};
struct empty {};
struct A : Clonable<A, empty> {};
struct B : Clonable<B, A> {};
It can be generalised to smart pointers and multiple bases if desired.
You could use a CRTP approach, but that has other drawbacks:
struct Base {
virtual Base* clone() const = 0;
};
template <typename Derived>
class BaseT : public Base {
// ...
public:
Base* clone() const override {
return new Derived(*static_cast<Derived*>(this));
}
};
Usage:
class DerivedA : public BaseT<DerivedA> {
};
Base *x = new DerivedA();
Base *y = x->clone();
I haven't keep track with the new features in recent C++ standards... Is there a way to avoid this in modern C++?
This trick is available since the c++98 standard.
If you can control how you pass around the polymorphic type, use type erasure. In particular, the proposed std::polymorphic_value calls the derived copy constructor when it is copied. You can imagine it as something like this:
template <typename B>
class polymorphic_value {
public:
template <typename D,
std::enable_if_t<
std::is_base_of<B, std::decay_t<D>>::value, int> = 0>
explicit polymorphic_value(D&& value)
: ptr{std::make_unique<derived_t<std::decay_t<D>>>(std::forward<D>(value))}
{}
polymorphic_value(polymorphic_value const& rhs)
: ptr{rhs.ptr->clone()}
{}
B const& get() const { return ptr->get(); }
B& get() {
// Safe usage of const_cast, since the actual object is not const:
return const_cast<B&>(ptr->get());
}
private:
struct base_t {
virtual ~base_t() = default;
virtual std::unique_ptr<B> clone() const = 0;
// With more effort, this doesn't have to be a virtual function.
// For example, rolling our own vtables would make that possible.
virtual B const& get() const = 0;
};
template <typename D>
struct derived_t final : public base_t {
explicit derived_t(D const& d)
: value{d}
{}
explicit derived_t(D&& d)
: value{std::move(d)}
{}
std::unique_ptr<B> clone() const override {
return std::make_unique<D>(value);
}
B const& get() const override {
return value;
}
D value;
};
std::unique_ptr<base_t> ptr;
};
For a thorough implementation which follows the proposal, see jbcoe's github repository.
Sample usage:
class Base {
public:
virtual ~Base() = default;
};
class Derived : public Base {
public:
Derived() = default;
Derived(Derived const&);
};
int main() {
polymorphic_value<Base> it{Derived{}};
auto const copy = it;
}
Live on Godbolt
You probably have a class where you store the polymorphic object and where you want to clone? Together with your polymorphic object you could store a function-pointer doing the cloning:
template<class Derived>
Base* clone(const Base* b) {
return new Derived(static_cast<const Derived*>(b));
}
void SampleUsage() {
Base* b = new Derived;
Base*(*cloner)(const Base*) = clone<Derived>;
Base* copy = cloner(b);
}
The type of cloner is independent of Derived. Its like a simplified std::function.
You can at minimum avoid writing the class name by getting it from the type of the class itself with:
struct A: public Base
{
Base* Clone() { return new std::remove_reference_t<decltype(*this)>(*this); }
};
Using CRTP will not help avoid duplicating the class name again, as you than have to write the class name inside the template parms for the CRTP base.
You could use CRTP to add an additional layer between your derived class and base that implements your cloning method.
struct Base {
virtual ~Base() = default;
virtual Base* clone() = 0;
};
template <typename T>
struct Base_with_clone : Base {
Base* clone() {
return new T(*this);
}
};
struct Derived : Base_with_clone<Derived> {};

How to enforce implementing the constructor of a specific data type on a derived class?

Given an abstract class A and a data type T, is there a way to enforce implementing a constructor of T on a derived class of A? i.e.
class A {
public:
virtual ~A() {}
virtual void foo() = 0;
};
class B : public A {
public:
B(T t) { ... } // this constructor must be implemented otherwise compilation will error out
};
It is possible with a private token based design. This idea looks something like the following:
#include <utility>
#include <memory>
class A{
private:
struct create_token
{
create_token(const create_token &) = delete;
create_token& operator=(const create_token &) = delete;
create_token(create_token &&) = default;
create_token& operator=(create_token &&) = default;
friend class A;
private:
create_token(){};
};
inline static auto token = create_token{};
protected:
A(create_token) {}
public:
template<class T, typename... ARGUMENTS>
static std::unique_ptr<T> create(ARGUMENTS&&... arguments)
{
// Whatever creation mechanism here
return std::make_unique<T>(create_token{}, std::forward<ARGUMENTS>(arguments)...);
}
};
class B : public A {
public:
template <typename Token> // Can't name A::create_token, it is private
B(Token tok) : A(std::move(tok)) {}
B(){} // Will always lack a `create_token`
};
The example needs a bit of modification for your case (mainly to restrict the constructor) - but the point is that construction can only go through the factory create function.
If A will have it's own constructor which takes parameter and no default constructor
class A {
public:
A(T t) {};
virtual ~A() {}
virtual void foo() = 0;
};
Then all derived classes have to initialize that in their constructor, which means at least one constructor will be needed.
See below examples:
class B : public A {
public:
B(T t):A(t) { ... } // pass parameter to A constructor
};
class C : public A {
public:
C(): A(T{}) { ... } // initialize A with a default T
};
class D : public A {
public:
using A::A; // inherit A's constructors
};
class E : public A {
public:
//error - doesn't work without any constructor!
};
You shouldn't try to force any constructor syntax in derived classes - they may know things which you don't know and they may or may not need T. I'm not sure if forcing constructor signature is even possible.
My best shot would be using CRTP, so that you can check the properties of the derived class within the base class:
template <class Derived>
class A_CRTP //: public A_Base
{
protected:
A() {
static_assert(sizeof(Derived{T}) > 0, "Constructor from T not present");
}
};
class B : public A_CRTP<B> {
public:
B();
B(T); // removing this is a compile-time error.
};
However, this is trivially bypassed:
class C : public B
{
C();
// No C(T) needed, B has that and A doesn't know about C.
};
https://godbolt.org/z/qzd_LJ
That makes this whole exercise somewhat pointless, as it just forces users to take extra steps before they can write the set of constructors they want (see answer of #Yksisarvinen).

CRTP - Is it possible to make an abstract base class?

I'm implementing a static polymorphism:
template<typename T>
class Base {
public:
void method() {
// do something
impl();
// do something else
}
void impl() { // intended to be private
static_cast<T*>(this)->impl();
}
};
class Derived : public Base<Derived> {
public:
void impl() { // intended to be private
}
};
This code is a static implementation of a dynamic polymorphic classes where void impl() was pure virtual. So the base class was abstract.
Now these classes implement static polymorphism and therefore don't have pure virtual functions.
Is it possible to make Base class abstract, so that objects of this class can't be created?
You can use a protected destructor and constructors:
template<typename T>
class Base {
public:
void method() {
// do something
impl();
// do something else
}
void impl() { // intended to be private
static_cast<T*>(this)->impl();
}
protected:
Base() = default;
~Base() = default;
// If you don't want to implement proper copying/moving:
// Base(const Base&) = delete;
// Base(Base&&) = delete;
// Base& operator=(const Base&) = delete;
// Base& operator=(Base&&) = delete;
};
This will even disallow a derived class's member functions to create base class objects, as well as trying to delete a pointer whose static type is Base<T>.

Is it possible to clone a polymorphic object without manually adding overridden clone method into each derived class in C++?

The typical pattern when you want to copy a polymorphic class is adding a virtual clone method and implement it in each derived class like this:
Base* Derived::clone()
{
return new Derived(*this);
}
Then in a calling code you can:
Base *x = new Derived();
Base *y = x->clone();
However if you have 50+ derived classes and realize you need polymorphic copy, it's tedious to copy-paste the cloning method into each of them. And it's essentially a boilerplate that works around a language limitation that you have to spell out the actual name to call the constructor.
I haven't keep track with the new features in recent C++ standards... Is there a way to avoid this in modern C++?
You can use this generic CRTP code
template <class Derived, class Base>
struct Clonable : Base {
virtual Base* do_clone() {
return new Derived(*static_cast<Derived*>(this));
}
Derived* clone() { // not virtual
return static_cast<Derived*>(do_clone());
}
using Base::Base;
};
struct empty {};
struct A : Clonable<A, empty> {};
struct B : Clonable<B, A> {};
It can be generalised to smart pointers and multiple bases if desired.
You could use a CRTP approach, but that has other drawbacks:
struct Base {
virtual Base* clone() const = 0;
};
template <typename Derived>
class BaseT : public Base {
// ...
public:
Base* clone() const override {
return new Derived(*static_cast<Derived*>(this));
}
};
Usage:
class DerivedA : public BaseT<DerivedA> {
};
Base *x = new DerivedA();
Base *y = x->clone();
I haven't keep track with the new features in recent C++ standards... Is there a way to avoid this in modern C++?
This trick is available since the c++98 standard.
If you can control how you pass around the polymorphic type, use type erasure. In particular, the proposed std::polymorphic_value calls the derived copy constructor when it is copied. You can imagine it as something like this:
template <typename B>
class polymorphic_value {
public:
template <typename D,
std::enable_if_t<
std::is_base_of<B, std::decay_t<D>>::value, int> = 0>
explicit polymorphic_value(D&& value)
: ptr{std::make_unique<derived_t<std::decay_t<D>>>(std::forward<D>(value))}
{}
polymorphic_value(polymorphic_value const& rhs)
: ptr{rhs.ptr->clone()}
{}
B const& get() const { return ptr->get(); }
B& get() {
// Safe usage of const_cast, since the actual object is not const:
return const_cast<B&>(ptr->get());
}
private:
struct base_t {
virtual ~base_t() = default;
virtual std::unique_ptr<B> clone() const = 0;
// With more effort, this doesn't have to be a virtual function.
// For example, rolling our own vtables would make that possible.
virtual B const& get() const = 0;
};
template <typename D>
struct derived_t final : public base_t {
explicit derived_t(D const& d)
: value{d}
{}
explicit derived_t(D&& d)
: value{std::move(d)}
{}
std::unique_ptr<B> clone() const override {
return std::make_unique<D>(value);
}
B const& get() const override {
return value;
}
D value;
};
std::unique_ptr<base_t> ptr;
};
For a thorough implementation which follows the proposal, see jbcoe's github repository.
Sample usage:
class Base {
public:
virtual ~Base() = default;
};
class Derived : public Base {
public:
Derived() = default;
Derived(Derived const&);
};
int main() {
polymorphic_value<Base> it{Derived{}};
auto const copy = it;
}
Live on Godbolt
You probably have a class where you store the polymorphic object and where you want to clone? Together with your polymorphic object you could store a function-pointer doing the cloning:
template<class Derived>
Base* clone(const Base* b) {
return new Derived(static_cast<const Derived*>(b));
}
void SampleUsage() {
Base* b = new Derived;
Base*(*cloner)(const Base*) = clone<Derived>;
Base* copy = cloner(b);
}
The type of cloner is independent of Derived. Its like a simplified std::function.
You can at minimum avoid writing the class name by getting it from the type of the class itself with:
struct A: public Base
{
Base* Clone() { return new std::remove_reference_t<decltype(*this)>(*this); }
};
Using CRTP will not help avoid duplicating the class name again, as you than have to write the class name inside the template parms for the CRTP base.
You could use CRTP to add an additional layer between your derived class and base that implements your cloning method.
struct Base {
virtual ~Base() = default;
virtual Base* clone() = 0;
};
template <typename T>
struct Base_with_clone : Base {
Base* clone() {
return new T(*this);
}
};
struct Derived : Base_with_clone<Derived> {};