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