C++ function in parent return child
You should use the CRTP.
template<class Derived>
class Entity
{
Derived* This() { return static_cast<Derived*>(this); }
public:
Derived& name(const string& name)
{
...
return *This();
}
};
class Client : public Entity<Client>
{
public:
Client& budgetRange(const long& range)
{
...
return *this;
}
};
If you want to use virtual functions, you can also add abstract base class, like this:
class AbstractEntity
{
public:
virtual void foo() = 0;
virtual ~AbstractEntity();
};
template<class Derived>
class Entity : AbstractEntity
{...};
The "curiously recursive template" pattern could help here; make the base class a template, parametrised by the derived class, along the lines of:
template <typename Derived>
struct Entity {
Derived & name(std::string const & name) {
// stuff
return static_cast<Derived&>(*this);
}
};
struct Client : Entity<Client> {
Client & budget(long range) {
// stuff
return *this;
}
};
Client().name("Mike").budget(50); // should compile
This will only work if all your types inherit directly from Entity
. If you need the types to be polymorphic (i.e. all share a common base class), then you'll need to add another non-template base class, and have Entity
inherit from that.
Now that nearly everything has already been said, I want to add a piece of answer that allows one to use the CRTP over multiple levels of inheritance:
The above CRTP implementations break when one wants to inherit from Client
, since Derived
will refer to Client
. In case you want to be able to carry the named parameter idiom over multiple levels of inheritance using CRTP pattern, you need to code your classes like so
template<class Derived>
class Entity_T
{
protected:
Derived* This() { return static_cast<Derived*>(this); }
public:
Derived& name(const string& name)
{
...
return *This();
}
};
template<class Derived>
class Client_T : public Entity_T<Derived>
{
Derived& budgetRange(const long& range)
{
...
return *This();
}
};
To provide the user a template-free version of Client_T
add
class Client : public Client_T<Client> {};
Whether or not this is worth the enlarged code base is entirely up to you. Note, that I haven't compiled the code above.