Conversion operator between classes derived from the model

advertisements

I have the following template classes, I need to figure out how to implement a conversion operator between the derived template classes.

template<class T>
class Base
{
public:
    Base () { }

    template <class U>
    operator Base<U>()
    {
        return Base<U> (v);
    }

    virtual double getV() = 0;

};

class D1: public Base<D1>
{
public:

    D1(int j)
    {
        i = j;
    }

    double getV() const { return i; }

    template <class U>
    operator Base<U>()
    {
        return Base<U>(getV());
    }

private:
    int i;
};

class D2: public Base<D2>
{
public:

    D2(int j)
    {
        i2 = j;
    }

    double getV() const { return i2; }

    template <class U>
    operator Base<U>()
    {
        return Base<U>(getV());
    }

private:
    int i2;
};

How can I achieve the following?

D1 d1(3);
D2 d2 = d1;  //conversion from 'D1' to non-scalar type 'D2' requested

if the design itself sound or should I be doing something else?

Please let me know what ur thoughts


In your example, I don't see a reason why CRTP is used.

The specializations of Base all have a virtual member function that is not dependent on the template parameter. Your code suggests this virtual member function can be used to access all data necessary to create an instance of any class derived from a specialization of Base. If we follow this assumption, one could rather think of:

class Base
{
public:
    virtual double getV() const = 0;
};

class D1 : public Base
{
    int i;
public:
    D1(int);
    virtual double getV() const { return i; }
};

class D2 : public Base
{
    int i;
public:
    D2(int);
    virtual double getV() const { return i; }
};

This still does not allow conversions. However, it is quite simple to add them here:

class D1 : public Base
{
    int i;
public:
    D1(int);
    D1(Base const& p) : D1(p.getV()) {}
    virtual double getV() const { return i; }
};

This conversion should be allowed by D1 and not by Base, because only D1 knows what data is required for it to be constructed.


If CRTP is necessary for things not shown here, you could still use a common base class:

class Common_base
{
public:
    virtual double getV() const = 0;
};

template<class T>
class Base : public Common_base
{
};

class D1 : public Base<D1>
{
    int i;
public:
    D1(int);
    D1(Common_base const& p) : D1(p.getV()) {}
    virtual double getV() const { return i; }
};

If, for some reason, the CRTP is required for the conversion, you could still use a converting constructor template:

template<class T>
class Base
{
public:
    virtual double getV() const = 0; // whyever
};

class D1 : public Base
{
    int i;
public:
    D1(int);
    template<class U>
    D1(Base<U> const& p) : D1(p.getV()) {}
    virtual double getV() const { return i; }
};