javaLover
javaLover

Reputation: 6425

CRTP to avoid code duplication : can't assignment Base=Derived by value

I have classes Base, Derived1, Derived2, etc.
It is compilable (below).

class Base{  };
class Derived1 : public Base{
    public: Derived1* operator->() { return this; }
    public: void f1(){}
};
class Derived2 : public Base{
    public: Derived2* operator->() { return this; }
};
class Derived3 : public Derived2{
    public: Derived3* operator->() { return this; }
};
int main(){//test case (my objective is to make all these work)
    Derived1 d1;  d1->f1();
    Base b=d1;              //non harmful object slicing
    Derived3 d3;
    Derived2 d2=d3;
}

Edit: I believe it is a non-harmful object slicing, and I think it is unrelated to the question.

Then, I want the operator->() to be inside Base, so I don't have to implement in all DerivedX class.

This is my attempt so far, using CRTP. It is uncompilable at # :-

class Base{  };
template<class T1,class T2>class Helper{
    public: T2* operator->() { return static_cast<T2*>(this); }
};
class Derived1 : public Helper<Base,Derived1>{
    public: void f1(){}
};
class Derived2 : public Helper<Base,Derived2>{    };
class Derived3 : public Helper<Derived2,Derived3>{    };
int main(){
    Derived1 d1;  d1->f1();
    Base b=d1;                    //#
    Derived3 d3;     
    Derived2 d2=d3;
}

I have read these two promising links (below), and do little progress (above) :-

Wiki states that casting Derive to Base is quite impossible for CRTP, so I feel that there might be no solution using CRTP.

Question:

I am new to CRTP (just play with it today). Sorry if it is duplicated.

Upvotes: 1

Views: 246

Answers (1)

skypjack
skypjack

Reputation: 50540

Put aside the slicing of your objects, your example works just fine if you define your helper as:

template<class T1, class T2>
class Helper: public T1 {
public:
    T2* operator->() {
        return static_cast<T2*>(this);
    }
};

That is:

  • Derive from T1 as if in a pure mixin based approach
  • Use T2 as if in a pure CRTP approach

If you consider the declaration of Derived1:

class Derived1: public Helper<Base, Derived1>;

It goes without saying that now Base b = d1; works, for Derived1 inherits directly from Base.

Upvotes: 2

Related Questions