I'm trying to create a named-arguments-like constructor for some of the classes of a project.
The way I'm doing it is by defining a class proxy which will hold the arguments and pass an instance of this proxy to the constructor of my classes.
Everything worked fine until I had to derive one of my classes.
Basically I thought: I'm gonna derive the new derived class proxy from the base class proxy. This works too, but only if I use only the derived proxy class arguments.
Here is an example since it is easier to understand:
class Person
{
public:
class PersonArgs
{
public:
const std::string& Name() const { return _name; }
PersonArgs& Name(const std::string& name)
{
_name = name;
return *this;
}
const std::string& Surname() const { return _surname; }
PersonArgs& Surname(const std::string& surname)
{
_surname = surname;
return *this;
}
protected:
std::string _name;
std::string _surname;
}
public:
Person()
: _name("")
, _surname("")
{ }
Person(const PersonArgs& args)
: _name(args.Name())
, _surname(args.Surname())
{ }
protected:
std::string _name;
std::string _surname;
}
class PersonEx : public Person
{
public:
class PersonExArgs : public Person::PersonArgs
{
public:
const std::string& Address() const { return _address; }
PersonExArgs& Address(const std::string& address)
{
_address = address;
return *this;
}
protected:
std::string _address;
}
public:
PersonEx()
: _address("")
{ }
PersonEx(const PersonExArgs& args)
: Person(args)
, _address(args.Address())
{ }
protected:
std::string _address;
}
int main(int argc, char** argv)
{
// This is ok since PersonExArgs::Address returns a PersonExArgs&
PersonEx* p1 = new PersonEx(PersonEx::PersonExArgs().Address("example"));
// This won't work since PersonExArgs::Name returns a PersonArgs&
PersonEx* p2 = new PersonEx(PersonEx::PersonExArgs().Address("example").Name("Mark"));
}
Basically, since I chain the arguments returning a reference to the proxy class instance when I set an argument, it breaks when using this from a derived proxy class since it will return a reference to the base proxy class and not the derived one, not allowing me to access the derived proxy arguments and neither pass it to the constructor of the derived class.
Anyone has an idea on how to fix this?
The most common solution to this problem is the Curiously Recurring Template Pattern (CRTP):
In your case, you could combine it with another base class to clean up the interface: