Invalid covariant type with CRTP clonable class

invalid covariant return type
crtp constructor
covariant return type c++
c unique_ptr to base class
c++ cloneable
crtp c++ advantages
is not covariant with the return type of the function it overrides
return unique_ptr from function

I'm trying to implement a Clonable class with the CRTP. However, I need to have abstract class that have a pure virtual clone method, overridden by child classes. To make this happen, I need the clone function to return a covariant return type. I made this code below, and the compiler shout at me this error:

main.cpp:12:5: error: return type of virtual function 'clone' is not covariant with the return type of the function it overrides ('B *' is not derived from 'AbstractClonable *')

The class 'B' seems to be a child class of AbstractClonable, and even by two way! How can I solve this? Thank you very much. I tried with both with clang 3.6 and GCC 4.9.2

struct AbstractClonable {
    virtual AbstractClonable* clone() const = 0;
};

template<typename T>
struct Clonable : virtual AbstractClonable {
    T* clone() const override {
        return new T{*dynamic_cast<const T*>(this)};
    }
};

struct A : virtual AbstractClonable {

};

struct B : A, Clonable<B> {

};

Even if B is indeed derived from Clonable<B>, the problem here is that Clonable<B> construction is not valid, as it defines

B* clone() const override

which of course is not an override of AbstractClonable::clone(), since the compiler doesn't see B at this point as a child of AbstractClonable. So I believe the issue lays in the fact that the compiler cannot build the Clonable<B> base of B.

A workaround (but not really the same as what you want) is to define

Clonable* clone() const override

in Clonable. As you mentioned in the comment, you can also define a free function

template<typename T> 
T* clone(const T* object) 
{ 
    return static_cast<T*>(object->clone()); 
}

Related: Derived curiously recurring templates and covariance

c++ - Invalid covariant type with CRTP clonable class -, i'm trying implement clonable class crtp. however, need have abstract class have pure virtual clone method, overridden child classes. make  "invalid covariant return type for" actually caused by the fact that you try to change the return type of getData(). Though return type isn't part of function identifier it still subject for some restriction. Any method that overrides some base class should behave similary.


Yes, B is derived from AbstractClonable, but the compiler doesn't know that during the instantiation of Clonable<B> because B is still incomplete at that point.

C++14 §10.3/8:

If the class type in the covariant return type of D::f differs from that of B::f, the class type in the return type of D::f shall be complete at the point of declaration of D::f or shall be the class type D.

A class has special permission to use itself in a covariant return type. Other classes, including CRTP bases, need to wait until the class is complete before declaring a covariant function.

You can solve the problem using the non-virtual interface idiom (NVI):

class AbstractClonable {
protected:
    virtual AbstractClonable* do_clone() const = 0;
public:
    AbstractClonable *clone() const {
        return do_clone();
    }
};

template<typename T>
class Clonable : public virtual AbstractClonable {
    Clonable* do_clone() const override { // Avoid using T in this declaration.
        return new T{*dynamic_cast<const T*>(this)};
    }
public:
    T *clone() const { // But here, it's OK.
        return static_cast< T * >( do_clone() );
    }
};

How to Return a Smart Pointer AND Use Covariance, The problem: Covariant return type vs. smart pointers class cloneable CRTP is a C++ idiom that enables the injection of the derived class  CRTP: The Curiously Recurring Template Pattern. Since C++98, the main recommended method is to use a variation of CRTP, the Curiously Recurring Template Pattern. The idea is that we instantiate a base class with our own type, and the base class provides the boilerplate we want.


I think the problem is that

T* clone() const override{
    return new T{*dynamic_cast<const T*>(this)};
}

returns B* instead of AbstractClonable *.

C++: Polymorphic cloning and the CRTP (Curiously Recurring , when you define the virtual clone() function in Vehicle as returning an object of type Vehicle, you can override the function in the derived class  Invalid covariant type with CRTP clonable class c++,multiple-inheritance,crtp,cloneable,covariant I'm trying to implement a Clonable class with the CRTP. However, I need to have abstract class that have a pure virtual clone method, overridden by child classes. To make this happen, I need the clone function to return a covariant return type.


Cannot create a proper clone method with shared_ptr – Musing , This requires a feature called covariant return types, which C++ class overriding the virtual function with a different return type. of those 'static_cast' statements will inevitably perform an invalid cast. Take a look at the clonable template in the above code. Using CRTP may solve this in some cases:. c++,multiple-inheritance,c++98,covariant. TL;DR Overriding foo in class D. foo methods can not covariant due to unrelated X and Y return types. Neither, can not overload due to different return types but same signature. Explanation Let's clean up the code to a smaller snippet with same issue: class X {}; class Y {};


GotW-ish: The 'clonable' pattern – Sutter's Mill, CRTP solution is probably the easiest, but most(all?) solutions here suffer from easy to forget issues: 1) the base class needs to have a virtual  Covariant Return Types and Smart Pointers. Covariant Return Types is language feature which allows you to change return type of your virtual function to covariant type ie. pointer to derived class instead of pointer to base class - see example below:


Using CRTP with virtual inheritance - c++ - android, Every node must be clonable but I don't want to write clone method to every node​. So I use CRTP. class Node { public: Node(){} Node(Fill*) { } virtual ~Node() Is there a way to overcome the bug, and still have covariant types is clone method? be syntactically invalid and has no meaningful semantics with regards to C++. As you can see, the concrete class is now free of clutter. This effectively adds a polymorphic and covariant clone() to a hierarchy of class. This CRTP is the foundation of our general solution: Every next step will build upon it. Multiple Inheritance: Variadic templates to the rescue. One complication of OO hierarchies is multiple inheritance.