Skip to main content
GameDev.net gamedev.net
🔒 Locked

A simple constness question (C++)

Started by twix Jul 30, 2007 at 9:49 PM 10 replies 1.4k views
Original Post
twix
twix
OK, so this has been irritating me for a while, and I'm hoping there's some simple workaround that I'm missing. Let's say I have this code:

class MyClass
{
public:

      Member const& GetMember() const;
      Member & GetMember();


private:
      Member myMember;
}

Now, let's say that GetMember contains a substantial amount of code, and both versions do exactly the same thing. I'd like to have one of them just call the other, but I can't have a const member call a non-const member, and I can't have the non-const version return a const reference! How can I do what I'm looking for here without duplicating the code?
mattnewport
mattnewport
It's legal but slightly ugly to call the const version of GetMember from the non const version and then const_cast the return value to a non-const Member object and return that. The standard says that const_cast leads to undefined behaviour if the object being cast was originally defined as const but since you've been called through a non-const object you know it wasn't originally defined as const (unless someone else has been abusing const_cast) so you can safely cast away the constness to return a non const reference.
dave
dave
If the code in question doesn't alter the returned object then move that into its own function and call it from both.
twix
twix
Even if the code doesn't modify the object, I still can't return a non-const reference from the auxiliary function. [sad]

I think I'll use mattnewport's method. Thanks!
dragongame
dragongame
Quote:
Original post by Dave
If the code in question doesn't alter the returned object then move that into its own function and call it from both.


Try this:
class MyClass{public:      Member const& GetMember() const { doTheWork(); return myMember; }      Member & GetMember() { doTheWork(); return myMember; }private:      void doTheWork() const;      Member myMember;}
“Always programm as if the person who will be maintaining your program is a violent psychopath that knows where you live”
twix
twix
Nah, it's no good.

I suppose my code was kind of misleading; I'm not just returning a single myMember each time. Most of the code is input validation and deciding what to return, so I can't pull that part of the code out.

I'm curious to know what you could do in a "void doTheWork() const;" function, though. [grin]
Julian90
Julian90
Quote:
I'm curious to know what you could do in a "void doTheWork() const;" function, though.


why std::cout << "Doing the work."; of coarse.
ToohrVyk
ToohrVyk
Quote:
Original post by twix
I suppose my code was kind of misleading; I'm not just returning a single myMember each time. Most of the code is input validation and deciding what to return, so I can't pull that part of the code out.


You can.

class MyClass{  typedef Member (MyClass::*MemberPointer);public:  Member const& GetMember() const { return (*this).*(ChooseMember()); }  Member& GetMember() { return (*this).*(ChooseMember()); }private:  MemberPointer ChooseMember()   {    return foo ? &MyClass::a : &MyClass::b;    }       Member a, b;};
twix
twix
Quote:
Original post by ToohrVyk
Quote:
Original post by twix
I suppose my code was kind of misleading; I'm not just returning a single myMember each time. Most of the code is input validation and deciding what to return, so I can't pull that part of the code out.


You can.

*** Source Snippet Removed ***

Well, I haven't tried compiling that, but doesn't it suffer from the exact same problem as the original?

Unless I'm misunderstanding how const works, in GetMember() const, "this" will be a const pointer, so you can't call ChooseMember unless it, too, is marked const.

But if you have "ChooseMember() const;", you shouldn't be able to return a nonconst MemberPointer without a const_cast... right?
ToohrVyk
ToohrVyk
Quote:
Original post by twix
But if you have "ChooseMember() const;", you shouldn't be able to return a nonconst MemberPointer without a const_cast... right?


The MemberPointer is not part of this—in fact, if you look closely at the code, it's a temporary value that's returned by value from ChooseMember.

Of course, being a temporary value, it can only be copied or manipulated by const reference. However, since operator .* uses the value of the member pointer to determine which member to return, it couldn't care less about the fact that the member pointer itself cannot be modified—what matters is that the member can be.

iMalc
iMalc
Sorry, without the actual code I'm at a loss for how to properly redesign this.
I just don't think I would ever have structured things in such a way as to even come across this problem though, well at least not for cases where there is any significant amount of code involved in each function.

However, The only reason I can see for a non-const 'GetMember' function is if you actually want to set something. I.e it seems to be that the non-const one should in fact be 'SetMember'. Or perhaps is would in fact be more like 'UpdateMember'. Though the best design change is probably a much bigger change.
klajerhgkja
klajerhgkja
Quote:
Original post by twix
I'm curious to know what you could do in a "void doTheWork() const;" function, though. [grin]
Throw an exception if the object is in an invalid state for calling GetMember, for example.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.