const and non-const version of the same fcn.

M

Mark P

Just wondering if there's a recommended approach for this:

class Foo
{
std:pair< Foo*, Foo* > bar();
std::pair< const Foo*, const Foo* > bar() const;
}

The two functions "do" the same thing logically, but for the const
version the return pair comprises pointers to constants. (You can think
of Foo as a linked list node that returns some other nearby nodes.)

Currently I have two essentially identical implementations modulo a few
uses of the keyword const. Is it better to implement the non-const
version in terms of the const version and const_cast the result?

Thanks for your advice,
Mark
 
V

Victor Bazarov

Mark P said:
Just wondering if there's a recommended approach for this:

class Foo
{
std:pair< Foo*, Foo* > bar();
std::pair< const Foo*, const Foo* > bar() const;
}

;
The two functions "do" the same thing logically, but for the const version
the return pair comprises pointers to constants. (You can think of Foo as
a linked list node that returns some other nearby nodes.)

Currently I have two essentially identical implementations modulo a few
uses of the keyword const. Is it better to implement the non-const
version in terms of the const version and const_cast the result?

I don't think so. Of course, it depends what the implementation does, but
you have to remember a simple rule: casting away constness by itself is not
dangerous, but changing the resulting non-const object has undefined
behaviour, unless it can be proven that originally the object was created
non-const, and you are simply returning it into its original state, so to
speak.

V
 
A

Alan Johnson

Mark said:
Just wondering if there's a recommended approach for this:

class Foo
{
std:pair< Foo*, Foo* > bar();
std::pair< const Foo*, const Foo* > bar() const;
}

The two functions "do" the same thing logically, but for the const
version the return pair comprises pointers to constants. (You can think
of Foo as a linked list node that returns some other nearby nodes.)

Currently I have two essentially identical implementations modulo a few
uses of the keyword const. Is it better to implement the non-const
version in terms of the const version and const_cast the result?

Thanks for your advice,
Mark

For what it is worth, Item 3 of Scott Meyer's /Effective C++/
recommends using const_cast in that situation. That is, you'd use
static_cast<const Foo &>(*this) to add const, and then const_cast the
result of the call to bar() to get rid of const.
 
V

Victor Bazarov

Alan Johnson said:
[..] That is, you'd use
static_cast<const Foo &>(*this) to add const, and then const_cast the
result of the call to bar() to get rid of const.


One cannot use 'static_cast' to add or remove const. It's prohibited by
the rules of the language. That's what 'const_cast' is for. If you are
talking about adding a const to ensure that the const version is called,
then it has to be a const_cast:

RetType r = const_cast<const Foo&>(*this)->same_member();

The problem still exists if 'same_member' returns a special object
created with 'const' in mind. If the parts of that object are created
'cosnt' to begin with, casting away constness to return them 'normal'
is improper. You basically need to reconstruct the non-const value
from the returned const value.

V
 
A

Andrey Tarasevich

Mark said:
Just wondering if there's a recommended approach for this:

class Foo
{
std:pair< Foo*, Foo* > bar();
std::pair< const Foo*, const Foo* > bar() const;
}

The two functions "do" the same thing logically, but for the const
version the return pair comprises pointers to constants. (You can think
of Foo as a linked list node that returns some other nearby nodes.)

Currently I have two essentially identical implementations modulo a few
uses of the keyword const. Is it better to implement the non-const
version in terms of the const version and const_cast the result?
...

Well, yes. That's what one would normally do in a case like this. The
only problem with your particular case is that the return types cannot
be converted to each other using a single cast, meaning that the
non-const version will look a little more complicated than it usually does:

std:pair< Foo*, Foo* > Foo::bar()
{
std::pair< const Foo*, const Foo* >& r =
const_cast<const Foo*>(this)->bar();
return std::pair< Foo*, Foo* >(const_cast<Foo*>(r.first),
const_cast<Foo*>(r.second)); // or use the 'std::make_pair' here
}
 
H

Heinz Ozwirk

Victor Bazarov said:
Alan Johnson said:
[..] That is, you'd use
static_cast<const Foo &>(*this) to add const, and then const_cast the
result of the call to bar() to get rid of const.


One cannot use 'static_cast' to add or remove const.

You cannot remove const with a static_cast, but you can add it. The standard
says that, among other cases, a static_cast can be used whenever for some
type T and some expression e, the definition const T t(e) is well-formed.
This is true for all pointer types, so (in the body of a member function of
class Foo) the definition

const Foo* p(this);

is well-formed and therefor static_cast<const Foo*>(this) is also valid.

Heinz
 
V

Victor Bazarov

Heinz said:
Victor Bazarov said:
Alan Johnson said:
[..] That is, you'd use
static_cast<const Foo &>(*this) to add const, and then const_cast
the result of the call to bar() to get rid of const.


One cannot use 'static_cast' to add or remove const.

You cannot remove const with a static_cast, but you can add it.

My bad. Of course, it's OK to add, not OK to remove.

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top