Covariant returns, inheritance, and named parameter idiom?!
First of all, sorry for the cross post but I am trying to elicit
responses from the standardistas as well as the mere mortals (like
myself) ;)
Well if the subject got your attention, then you might be able to make
some sense out of what I am trying to do here and explain to me why it
doesn't work. In brief, I'm working through some options for
implementing the named parameter idiom. What I would like to do is to
have classes include an inner class named "options" and accept an
options instenad as the only argument to a constructor. The options
class would implement setter functions that simply set a member and
return a reference to ``this''. Pretty simple (right?) and a common
implementation to do chaining. The difficulty comes when we start doing
inheritance. I planned on implementing this using something like the
following:
struct Base {
struct options {
virtual ~options() {}
virtual options& setBaseOption (int x) {
m_x = x;
return *this; }
int m_x;
};
Base (options& opts) : m_baseOptions(opts) {}
virtual ~Base() {}
options m_baseOptions;
};
struct Derived : public Base {
struct options : Base::options {
virtual ~options() {}
virtual options& setDerivedOption (int y) {
m_y = y;
return *this; }
int m_y;
};
Derived (options& opts) : Base(opts), m_derivedOptions(opts) {}
virtual ~Derived() {}
options m_derivedOptions;
};
int
main()
{
Derived object(Derived::options()
.setBaseOption(1)
.setDerivedOption(2));
return 0;
}
Now this doesn't work with g++ 4.0.1:
covariant.cpp: In function 'int main()':
covariant.cpp:32: error: 'struct Base::options' has no member named
'setDerivedOption'
I think that it should! I did a bunch of other variations using
pointers instead of references and stuff like that without any better
results. Is this a case of g++ not implementing covariant returns
properly? I've showed that at runtime this would work - inside of
setBaseOption, typeid(this) does return the expected type (Derived).
However, it looks like the compiler is statically typing the return
value of setBaseOption to Base&. Is this correct?
Do I have to explicitly override setBaseOption inside of
Derived::options to make this work? This does the trick for g++, but is
it required by the ANSI/ISO standard? For example, adding the following
member to Derived::options makes things work, but I really don't want
to do this.
virtual options& setBaseOption (int x) {
Base::options::setBaseOption(x);
return *this;
}
It is going to make maintenance of the class hierarchy a nightmare
since it requires you to modify every derived class whenever you modify
a base class :(
Has anyone out there tried anything like this? I'm really trying to get
the named parameters idiom to work for a class hierarchy that allows
for sub classes to pass base class parameters back up to the hierarchy
seemlessly. Is there a better approach out there?
Thanks in advance,
Dave.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]