class Test
{
public:
typedef boost::function<void()> Action;
void action()
{
}
Action getAction() const
{
return boost::bind(&Test::action, this);
}
};
Above code does not compile on Visual Studio 2005 Express Edition
because getAction is a "const" method. Is this compliant with the
standard? This seems counterintuitive to me since the state of the
object is not changed by calling this method.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
francis.rammeloo (37)
|
8/12/2008 2:41:28 PM |
|
I don't understand your problem and requirement.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
PeterAPIIT
|
8/13/2008 12:27:18 PM
|
|
Hello Francis,
your code doesn't compile because the pointer 'this' is of type 'const
Test*' within your const member function 'Test::getAction()'. You're
trying to bind this const pointer as first parameter to the non-const
member function Test::action() which expects a non-const pointer Test*
as first parameter. Your compiler is certainly rejecting ill-formed
code in this regard because the standard doesn't allow implicit const
casts.
The solution is to make both member functions either const or non-
const. This makes their 'this' pointers of the same type and doesn't
require an ugly const_cast in Test::getAction().
Note, that if it did compile you'd be able to do something like this:
void do_something(const Test& x)
{ x.getAction()(); }
which might change the object even though a const reference has been
passed to the function. It works against the idea of constness.
Cheers,
SG
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
SG
|
8/13/2008 12:58:29 PM
|
|
On 12 Aug., 22:41, francis_r <francis.ramme...@gmail.com> wrote:
> class Test
> {
> public:
> typedef boost::function<void()> Action;
>
> void action()
> {
> }
>
> Action getAction() const
> {
> return boost::bind(&Test::action, this);
> }
>
> };
>
> Above code does not compile on Visual Studio 2005 Express Edition
> because getAction is a "const" method. Is this compliant with the
> standard? This seems counterintuitive to me since the state of the
> object is not changed by calling this method.
I'm thinking the compiler is right. In a const method you are trying
to
provide a none const access to your method "action"! "action" is
allowed
to change the content...
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Thomas
|
8/13/2008 12:58:30 PM
|
|
francis_r wrote:
> class Test
> {
> public:
> typedef boost::function<void()> Action;
>
> void action()
> {
> }
>
> Action getAction() const
> {
> return boost::bind(&Test::action, this);
> }
> };
>
> Above code does not compile on Visual Studio 2005 Express Edition
> because getAction is a "const" method. Is this compliant with the
> standard?
Yes. The point is that 'this' is a pointer to a const Test, while bind would
need a pointer to a non-const Test. BTW, I guess you could have reduced the
example even further:
...
void getAction() const
{
boost::bind( &Test::action, this); // anonymous temporary
}
...
> This seems counterintuitive to me since the state of the
> object is not changed by calling this method.
By the same logic, you would also be able to return references to non-const
members from const memberfunctions, after all returning a reference doesn't
change them. No, if that would compile, it would be a hole in the
const-ness of the object, so it shouldn't.
Uli
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Ulrich
|
8/13/2008 12:58:31 PM
|
|
On Aug 13, 10:58 pm, Ulrich Eckhardt <dooms...@knuut.de> wrote:
> francis_r wrote:
> > class Test
> > {
> > public:
> > typedef boost::function<void()> Action;
>
> > void action()
> > {
> > }
>
> > Action getAction() const
> > {
> > return boost::bind(&Test::action, this);
> > }
> > };
>
> > Above code does not compile on Visual Studio 2005 Express Edition
> > because getAction is a "const" method. Is this compliant with the
> > standard?
>
> Yes. The point is that 'this' is a pointer to a const Test, while bind would
> need a pointer to a non-const Test. BTW, I guess you could have reduced the
> example even further:
>
> ...
> void getAction() const
> {
> boost::bind( &Test::action, this); // anonymous temporary
> }
> ...
>
> > This seems counterintuitive to me since the state of the
> > object is not changed by calling this method.
>
> By the same logic, you would also be able to return references to non-const
> members from const memberfunctions, after all returning a reference doesn't
> change them. No, if that would compile, it would be a hole in the
> const-ness of the object, so it shouldn't.
Interestingly enough, it does compile in VS2008 when using its own
std::tr1 implementation for function & bind, rather than Boost. Thanks
for clarifying why this is a problem - I've reported it to MS as a
bug:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=361784
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Pavel
|
8/14/2008 4:36:51 PM
|
|
On Aug 12, 4:41 pm, francis_r <francis.ramme...@gmail.com> wrote:
> Above code does not compile on Visual Studio 2005 Express Edition
> because getAction is a "const" method. Is this compliant with the
> standard? This seems counterintuitive to me since the state of the
> object is not changed by calling this method.
In this case, there's absolutely nothing wrong with a 'const_cast',
but the compiler is correct in not implicitly converting 'this' to a
pointer to non-const.
Kevin P. Barry
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
ta0kira
|
8/21/2008 7:28:34 AM
|
|
On 21 Aug., 15:28, ta0k...@yahoo.com wrote:
> On Aug 12, 4:41 pm, francis_r <francis.ramme...@gmail.com> wrote:
>
> > Above code does not compile on Visual Studio 2005 Express Edition
> > because getAction is a "const" method. Is this compliant with the
> > standard? This seems counterintuitive to me since the state of the
> > object is not changed by calling this method.
>
> In this case, there's absolutely nothing wrong with a 'const_cast',
> but the compiler is correct in not implicitly converting 'this' to a
> pointer to non-const.
> Kevin P. Barry
>
In this case - as is usually the case - there is everything wrong with
a const_cast. We must presume that the caller wants to use the
function, and if he does so, our constant object will be changed -
possibly resulting in undefined behaviour.
/Peter
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
peter
|
8/21/2008 3:02:12 PM
|
|
On Aug 21, 5:02 pm, peter koch larsen <peter.koch.lar...@gmail.com>
wrote:
> In this case - as is usually the case - there is everything wrong with
> a const_cast. We must presume that the caller wants to use the
> function, and if he does so, our constant object will be changed -
> possibly resulting in undefined behaviour.
The function doesn't modify the instance with the 'const_cast', and
what happens after the function's return isn't the concern of that
function. Sure, if the object is unconditionally 'const' then that
would be undefined behavior, but otherwise the 'const'-ness of the
function isn't compromised. In this case it's the class' author's
responsibility to document that calling the 'getAction' function on a
'const'-defined instance causes undefined behavior. In fact, I can't
think of a *more* appropriate circumstance to use a 'const_cast',
though such a move requires minor documentation for proper usage, as
does nearly every other non-trivial interface.
Kevin P. Barry
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
ta0kira
|
8/22/2008 12:47:22 AM
|
|
On 12 Aug, 21:41, francis_r <francis.ramme...@gmail.com> wrote:
> class Test
> {
> public:
> typedef boost::function<void()> Action;
>
> void action()
> {
> }
>
> Action getAction() const
> {
> return boost::bind(&Test::action, this);
> }
>
> };
>
> Above code does not compile on Visual Studio 2005 Express Edition
> because getAction is a "const" method. Is this compliant with the
> standard? This seems counterintuitive to me since the state of the
> object is not changed by calling this method.
If your reasoning were valid the following would also be allowed:
class Test
{
public:
typedef int& Action;
int action;
Action getAction() const
{
return action;
}
void ModifyConst() const
{
getAction() = 42;
}
};
You will see that getAction does not modify the state of the object
and yet this is clearly wrong for exactly the same reason that
your example is wrong.
The general principal for const-correctness is that given only a
pointer to a const object you should never be able to call a non-const
method or modify a non-mutable value without explicitly casting away
constness.
Clearly your example is not const-correct:
const Test* tp;
tp->getAction()(); // calling non-const method
You can no-more be "a bit" const-correct than you can be "a bit"
pregnant.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Nick
|
8/22/2008 7:00:38 AM
|
|
On 22 Aug., 08:47, ta0k...@yahoo.com wrote:
> On Aug 21, 5:02 pm, peter koch larsen <peter.koch.lar...@gmail.com>
> wrote:
>
> > In this case - as is usually the case - there is everything wrong with
> > a const_cast. We must presume that the caller wants to use the
> > function, and if he does so, our constant object will be changed -
> > possibly resulting in undefined behaviour.
>
> The function doesn't modify the instance with the 'const_cast', and
> what happens after the function's return isn't the concern of that
> function.
But it is of concern for those who of us who want the compiler to
assist us in writing maintainable code. The const was invented for
precisely this purpose.
Also note that a const prevents us to return pointers or references to
modifiable member-variables. In this situation, however, one could
imagine just reading the variable. When you return a function object
there is not much else to do with the object than to call the
function.
> Sure, if the object is unconditionally 'const' then that
> would be undefined behavior, but otherwise the 'const'-ness of the
> function isn't compromised. In this case it's the class' author's
> responsibility to document that calling the 'getAction' function on a
> 'const'-defined instance causes undefined behavior.
I can only say that i can not at all agree with you on that point.
Circumventing the type system is a very bad thing to do.
> In fact, I can't
> think of a *more* appropriate circumstance to use a 'const_cast',
> though such a move requires minor documentation for proper usage, as
> does nearly every other non-trivial interface.
A const_cast is primarily a means to cope with legacy libraries that
fails to respect const-correctness - perhaps because of the age of
that library, perhaps because it is written in a language without the
notion of constness. I can't really find any other legitimate usage
for const_casts.
I don't believe I've ever created a library that consciously broke
constness, and I doubt anyone could provide a motivating case for
that.
/Peter
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
peter
|
8/22/2008 6:44:50 PM
|
|
On Aug 22, 5:44 pm, peter koch larsen <peter.koch.lar...@gmail.com>
wrote:
>
> A const_cast is primarily a means to cope with legacy libraries that
> fails to respect const-correctness - perhaps because of the age of
> that library, perhaps because it is written in a language without the
> notion of constness. I can't really find any other legitimate usage
> for const_casts.
Well first there is delegation of a non-const method to a const
method. Without const_cast you'd often have to copy/paste code which
is infinitely worse.
Then there is one situation that sometimes happens when using proxy
classes by pointer. Consider the following very simplified scenario:
class foo;
class proxy
{
friend class foo;
public:
void do_const() const
{ m_p->const_method(); }
void do_non_const()
{ m_p->non_const_method(); }
private: //for friends only
proxy(foo * p) : m_p(p)
{}
private:
//non-copyable
proxy(const proxy &);
void operator=(const proxy &);
private:
foo * m_p;
};
class foo
{
public:
const proxy * get_proxy() const
{ return new proxy(const_cast<foo*>(this)); }
proxy * get_proxy()
{ return new proxy(this); }
void const_method() const
{}
void non_const_method()
{}
};
Note that const correctness is not violated here since const proxy can
only invoke const methods on foo. It is possible, of course, to have a
separate const_proxy class to handle this but that's again needless
code duplication (or needless template) for no particular gain IMO.
(This is different from STL iterators which by-value semantics doesn't
allow any other approach)
--
Eugene
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Eugene
|
8/23/2008 5:58:45 PM
|
|
peter koch larsen wrote:
>
> A const_cast is primarily a means to cope with legacy libraries that
> fails to respect const-correctness - perhaps because of the age of
> that library, perhaps because it is written in a language without the
> notion of constness. I can't really find any other legitimate usage
> for const_casts.
> I don't believe I've ever created a library that consciously broke
> constness, and I doubt anyone could provide a motivating case for
> that.
I do not agree. For me one of the commonest use of const_cast is for
avoiding const poisoning:
atype const * foo(atype const * a_ptr);
inline atype * foo(atpe * a_ptr){
return const_cast<atype *>(foo(const_cast<atype const *> a_ptr));
}
Not that this avoids either adding a gratuitous const qualifier when foo
is called whilst ensuring that const qualification status quo is
retained. The mechanism is guaranteed to be safe and effectively is
saying 'keep same qualification for the return value that was in the
argument.'
--
Note that robinton.demon.co.uk addresses are no longer valid.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Francis
|
8/23/2008 5:58:46 PM
|
|
On 24 Aug., 01:58, Eugene Gershnik <gersh...@gmail.com> wrote:
> On Aug 22, 5:44 pm, peter koch larsen <peter.koch.lar...@gmail.com>
> wrote:
>
>
>
> > A const_cast is primarily a means to cope with legacy libraries that
> > fails to respect const-correctness - perhaps because of the age of
> > that library, perhaps because it is written in a language without the
> > notion of constness. I can't really find any other legitimate usage
> > for const_casts.
>
> Well first there is delegation of a non-const method to a const
> method. Without const_cast you'd often have to copy/paste code which
> is infinitely worse.
>
> Then there is one situation that sometimes happens when using proxy
> classes by pointer. Consider the following very simplified scenario:
[scenario snipped]
I fully agree with you (and Francis). const_cast has other uses than
described by me above. What I was trying to state in my statement
above was about const_cast'ed values "leaking" to the environment,
either by passing the casted value to a foreing function or by
returning the value to the outside.
const_cast are most usable in situations as above, where you in a
controlled manner reuse the result of a non-const function.
/Peter
/Peter
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
peter
|
8/24/2008 8:57:56 PM
|
|
|
13 Replies
92 Views
(page loaded in 0.162 seconds)
|