Re: Using a macro to simplify implementing non-const methods in terms of const overload
Nick Hounsome wrote:
On 25 Aug, 12:41, "Martin T." <0xCDCDC...@gmx.at> wrote:
Hi all.
Implementing a non-const function in terms of it's const overload is an
accepted idea:
Occasionally (maybe in your real class?) but your examples and most
others that I have come across are actually just bad design.
Hmmm ... you mean to say that it is a sign of bad design if a member
function needs a cost and non-const version ??
class foo {
public:
std::string & bar() {
This is a bad example because it exposes the implementation of foo
(foo MUST contain a std::string).
Even worse it allows a client to maintain a reference to the guts of a
foo after the object has been destroyed:
foo* fp = new foo;
std::string& s( fp->bar() );
delete fp;
s.length(); // ooops! Undefined behaviour.
To keep the implementation hidden you must instead have something like
"void setbar(const std::string&)" and your use of the const bar()
would nolonger be relevant. Contrariwise, if foo were really intended
to be just a glorified struct then bar_ should be public and you would
have no need for either method.
While I don't agree that the reference returning is such a bad thing,
you do raise a valid point. Namely whether it's necessary to have such
accessors in the first place.
There are valid cases where we want to return a pointer/reference/handle
like thing from a mem.fun. and for these cases I think it makes sense to
provide a const + non-const version.
One example are the std library containers -- Consider this snippet from
std::vector from the STL supplied with Visual Studio 2008 Express:
// vector, line 758:
const_reference operator[](size_type _Pos) const
{ // subscript nonmutable sequence
#if _HAS_ITERATOR_DEBUGGING
if (size() <= _Pos)
{
_DEBUG_ERROR("vector subscript out of range");
_SCL_SECURE_OUT_OF_RANGE;
}
#endif /* _HAS_ITERATOR_DEBUGGING */
_SCL_SECURE_VALIDATE_RANGE(_Pos < size());
return (*(_Myfirst + _Pos));
}
reference operator[](size_type _Pos)
{ // subscript mutable sequence
#if _HAS_ITERATOR_DEBUGGING
if (size() <= _Pos)
{
_DEBUG_ERROR("vector subscript out of range");
_SCL_SECURE_OUT_OF_RANGE;
}
#endif /* _HAS_ITERATOR_DEBUGGING */
_SCL_SECURE_VALIDATE_RANGE(_Pos < size());
return (*(_Myfirst + _Pos));
}
I think it would kind of make sense to use the solution with the
const_cast instead of 1:1 duplicating 9 lines of code.
Microsoft (or whoever their STL comes from) didn't, maybe they had a
reason. My initial posting was trying to find out. :-)
return const_cast< std::string& >( static_cast<foo
const*>(this)->bar() );
}
const std::string & bar() const {
return bar_;
}
void mooh() {
This method is NEVER necessary - Just delete it and nobody will ever
know the difference.
Agreed. I was just over eager to supply a completeish example.
cheers,
Martin
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]