Re: Using a macro to simplify implementing non-const methods in terms of const overload
class foo
{
public:
std::string& bar() {return bar_;}
const std::string& bar() const {return bar();}
private:
std::string bar_;
};
It compiles. But it doesn't do what you think. It's an infinite
recursion. You get the behaviour you want by writing
Yeah sorry, FAIL! VS2008 would have given me a compile time warning had I
thought before typing.
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 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.
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);}
void Display() const
{
printf("count=%d\n",_Count);
for (std::vector<Thing>::size_type i=0;i<_V.size();i++) printf("%d: k=%d,
s=%s\n",i,_V[i].k,_V[i].s.c_str());
}
private:
std::vector<Thing> _V;
int _Count;
};
int main(int argc, char* argv[])
{
const foo t;
t.Display();
const Thing& thing1=t.bar(1);
t.Display();
// lets force a cast just because we can
Thing& thing2 = const_cast<foo*>(&t)->bar(2);
thing2.s="oops?";
t.Display();
}
I don't see the problem or the UB - seriously please tell me if there is a
problem here. It behaves as intended with VS2008 & GCC even the forced
removal of the const. Can you give me a realistic example of the "oops" with
casting through to the non-const bar()?
Regards,
Chris
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]