method chaining with polymorphism c++

c++, fluent, polymorphism

Solution

I think you could utilize CRTP here, something like the following, where the derived class tells the base what type it is:

class Base
{
    // Abstract/virtual interface here.
};

template <class Derived>
class Base_T : public Base
{
private:
    std::string mFoo;

public:
    Derived& withFoo(std::string foo) {
        mFoo = foo;
        return *static_cast<Derived*>(this);
    }
};

class Derived : public Base_T<Derived> {
private:
    std::string mBar;
public:
    Derived& withBar(std::string bar) {
        mBar = bar;
        return *this;
    }

    void doOutput() {
        std::cout << "Foo is " <<
            mFoo << ".  Bar is " <<
            mBar << "." << std::endl;
    }
};

Problem

Is it possible to write fluent chanining methods that return a derived type? Consider the following two classes: ``` class Base { protected: std::string mFoo; public: Base& withFoo(std::string foo) { mFoo = foo; return *this; } }; class Derived : public Base { protected: std::string mBar; public: Derived& withBar(std::string bar) { mBar = bar; return *this; } void doOutput() { std::cout << "Foo is " << mFoo << ". Bar is " << mBar << "." << std::endl; } }; ``` I would then like to build my object and use it like this: ``` Derived d; d.withFoo("foo").withBar("bar").doOutput(); ``` This of course fails since `withFoo` returns a `Base`. Since all my `with` methods simply set member variables, I can specify the derived `with`s first. The problem is my builder method (`doOutput` in the example above) would then need to be a separate statement. ``` Derived d; d.withBar("this is a bar") .withFoo("this is my foo"); d.doOutput(); ``` My question is whether there is some way for `withFoo` to return an unknown derived type so that `Base` may be used seamlessly with multiple derived classes (after all, `*this` is a `Derived`, although `Base` (correctly) is unaware of the fact). For a more concrete example, I'm writing a few classes to access a REST server. I have a `RestConnection` class with method `withUrl`, a `PostableRest` class with methods `withParam` and `doPost`, and a `GettableRest` class with `doGet`. I suspect this is not possible and will probably try cramming a bunch of virtual methods into `RestConnection` but I hate to do that when there are multiple `withParam`s overloaded, some of which don't make sense to include in a GET parameter list. Thanks in advance!

Original source