Suppose I have a base class and two classes derived from it:
class Base
{
protected:
double value;
public:
virtual ~Base();
Base(double value) : value(value) {}
Base(const Base& B) { value=B.value; }
Base operator+ (const Base& B) const {
return Base(value+B.value);
}
};
class final Derived1 : public Base {
public:
Derived1(double value) : Base(value) {}
};
class final Derived2 : public Base {
public:
Derived2(double value) : Base(value) {}
};
I want to accomplish the following:
int main(int argc, char *argv[])
{
Derived1 a = Derived1(4.0);
Derived2 b = Derived2(3.0);
a+a; // this should return a Derived1 object
b+b; // this should return a Derived2 object
a+b; // this should FAIL AT COMPILE TIME
return 0;
}
In other words, I want to guarantee that the inherited operator+ only operates on objects of the same type as the calling instance.
How do I do this cleanly? I found myself re-defining the operator for each class:
class final Derived1 : public Base {
...
Derived1 operator+ (const Derived1& D1) const {
return Derived1(value+D1.value);
}
...
};
class final Derived2 : public Base {
...
Derived2 operator+ (const Derived2& D1) const {
return Derived2(value+D1.value);
}
...
};
But that’s just a pain. Moreover, it doesn’t seem like proper code re-use to me.
What is the proper technique to use here?
If you can make sure
Derived1andDerived2are leaf classes (i.e. no other class can derive from them) you can do this with the curiously recurring template pattern:(
finalis a C++11 feature that prevents further derivation.)If you allow derivation from
Derived1andDerived2then you get trouble:There’s no way to prevent this at compile-time. And even if you want to allow it, it’s not easy to get decent semantics for this operation without multiple dispatch.