Re: Using a macro to simplify implementing non-const methods in terms of const overload
Chris Morley wrote:
SG wrote:
class foo
{
public:
std::string& bar() {return bar_;}
const std::string& bar() const
{
return const_cast<foo*>(this)->bar();
}
private:
std::string bar_;
};
^ This _is_ what I intended.
But that's really a very bad idea because
(*) it's easier to accidentally violate const correctness
(*) if you accidentally modify something in the non-const version
of bar() you will invoke undefined behaviour in cases like
const foo f; // f is really const!
f.bar(); // Ooops!
I'm not sure it is all that bad because you'd only want such a construct
It IS very very bad for the reasons I mentioned above.
in a situation where you are doing something trivial like returning a
reference/pointer to a structure/class. Perhaps you have a usage counter but
otherwise the non-const version would be as trivial as "return x;". More
complexity with different requirements for const & non-const function
version should hint that they need different function names.
I don't understand why you prefer to risk const correctness violations
and/or UB. You don't have the problems I mentioned above if you write
the non-const version in terms of the const version.
Here is a slightly less trivial but still similar complete program.
#include "stdio.h"
#include <string>
#include <vector>
struct Thing {
Thing() : k(0), s("init") {}
int k;
std::string s;
};
class foo {
public:
foo() : _Count(0) {_V.resize(3);}
Thing& bar(int n) {++_Count; return _V[n];}
const Thing& bar(int n) const {return const_cast<foo*>(this)->bar(n);}
Did I already say that this is a very VERY bad idea? (hint hint)
You convert a foo const* to a foo*. This allows you to accidentally
violate const correctness and leads to UB if you modify the object's
state in case it REALLY is a const object.
private:
std::vector<Thing> _V;
int _Count;
};
int main(int argc, char* argv[])
{
const foo t;
const Thing& thing1=t.bar(1);
Undefined behaviour! You're trying to modify t._Count but t IS CONST!
Alternativly you could have written:
foo s;
const foo& t = s;
const Thing& thing1=t.bar(1);
This is NOT UB because t ist just a const ref to s but s is non-const.
Still, it's a very VERY bad idea for reasones that have been mentioned
a couple of times by now.
Another example just for you:
int x = 23;
int const y = 42;
int const& z = x;
const_cast<int&>(y) = 99; // UB!
const_cast<int&>(z) = 99; // Ugly but fine
Cheers!
SG
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]