I have a task to implement a simple SVG generator. I need to support Circle, Polyline and Text. All three have at least 4 common methods: - SetStrokeColor - SetFillColor - SetStrokeWidth - ToString One of the main requirements is to support chaining, e.g.: Polyline{}.SetStrokeColor("white").SetFillColor("black")...
I decided to implement a base class Element, which all the other classes inherit from. The idea is to have a class Document that holds a vector of all the elements added to the document. A sample signature for a base method:
// source of trouble
Element &SetStrokeColor(const Color &color) {
...
return *this;
}
My derived classes do call these methods, but the trouble is that the methods return a reference to the base class Element, not the derived class.
My question is whether it is all together possible to implement in c++???
Further discussion here
If you want to share implementations and preserve type information, the CRTP is what you need:
struct ElementBase { };
template <class Concrete>
struct Element : ElementBase {
Concrete &setStrokeWidth(int width) {
// Actual implementation...
(void) width;
return cthis();
}
private:
friend Concrete;
Element() = default;
Concrete &cthis() { return static_cast<Concrete &>(*this); }
Concrete &cthis() const { return static_cast<Concrete const &>(*this); }
};
struct Circle : Element<Circle> {
Circle &SetCircleCenter(int x, int y) {
// Actual implementation...
(void) x;
(void) y;
return *this;
}
};
int main() {
Circle c;
c.setStrokeWidth(4).SetCircleCenter(0, 0);
}
See it live on Wandbox
With covariant return types, you can
class Element {
public:
// ...
virtual Element& refToThis() { return *this; };
};
and in derived classes
class Derived : public Element {
public:
// ...
Derived& refToThis() override { return *this; };
};
which lets you handle Derived
instances as Derived
instances when the static type is Derived
(e.g. inside Derived
itself). When tht static type is Element
, the return type of refToThis()
is, too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With