Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Question about const_cast

1 view
Skip to first unread message

Alex Howlett

unread,
Jan 11, 2007, 2:17:24 PM1/11/07
to
The compiler I use (Visual C++ 2005) will not compile the following
code:

----------------------------------
int main (int argc, char * argv[])
{
const int test1 = 5;
const int test2 = const_cast<const int> (test1);

return 0;
}
----------------------------------
Error 1 error C2440: 'const_cast' : cannot convert from 'const
int' to 'int' j:\test\main.cpp 4
----------------------------------

So I looked to the standard and found that section 5.2.11 had this to
say this about const_cast:

----------------------------------
1. The result of the expression const_cast<T>(v) is of type T. If T is
an lvalue reference type,

the result is an lvalue; otherwise, the result is an rvalue and the
lvalue-to-rvalue (4.1), array-to

poitner (4.2), and function-to-pointer (4.3) standard conversions are
performed on the expression v. Types shall not be defined in
const_cast. Conversions that can be performed explicitly using
const_cast are listed below. No other conversion shall be performed
explicitly using const_cast.

2. [Note: Subject to the restrictions in this section, an expression
may be cast to its own type using a const_cast operator. --end note]
----------------------------------

I read through the whole section and I don't see any restrictions on
casting an expression to its

own type.

The Microsoft folks insist that this behavior is correct.

Here's the thread I posted in:

http://forums.microsoft.com/MSDN/showpost.aspx?postid=1097601&siteid=1&PageID=0

I hate to pick nits, but the standard appears to support this
functionality and it would be very useful to me were it available in my
compiler. Is there something I'm missing?

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

Jim Langston

unread,
Jan 11, 2007, 4:36:50 PM1/11/07
to

"Alex Howlett" <a.l_e.x_AT.s_u.n_c.h_o.D@T_c.o_m> wrote in message
news:mn.5b557d71c...@Tc.om...

> The compiler I use (Visual C++ 2005) will not compile the following code:
>
> ----------------------------------
> int main (int argc, char * argv[])
> {
> const int test1 = 5;
> const int test2 = const_cast<const int> (test1);
>
> return 0;
> }
> ----------------------------------
> Error 1 error C2440: 'const_cast' : cannot convert from 'const
> int' to 'int' j:\test\main.cpp 4
> ----------------------------------

I think it's worst than you think. This won't compile either (VC++ 2003)

int main ()
{


int test1 = 5;
const int test2 = const_cast<const int> (test1);
}

error C2440: 'const_cast' : cannot convert from 'int' to 'int'

It won't even cast a non const int to a const int in that statement. I
don't know why.

Alex Howlett

unread,
Jan 11, 2007, 5:07:58 PM1/11/07
to
Jim Langston laid this down on his screen :

> "Alex Howlett" <a.l_e.x_AT.s_u.n_c.h_o.D@T_c.o_m> wrote in message
> news:mn.5b557d71c...@Tc.om...
>> The compiler I use (Visual C++ 2005) will not compile the following code:
>>
>> ----------------------------------
>> int main (int argc, char * argv[])
>> {
>> const int test1 = 5;
>> const int test2 = const_cast<const int> (test1);
>>
>> return 0;
>> }
>> ----------------------------------
>> Error 1 error C2440: 'const_cast' : cannot convert from 'const int'
>> to 'int' j:\test\main.cpp 4
>> ----------------------------------
>
> I think it's worst than you think. This won't compile either (VC++ 2003)
>
> int main ()
> {
> int test1 = 5;
> const int test2 = const_cast<const int> (test1);
> }
>
> error C2440: 'const_cast' : cannot convert from 'int' to 'int'
>
> It won't even cast a non const int to a const int in that statement. I don't
> know why.
>

Casting a non-const int to a const int by value is not one of the
conversions listed in section 5.2.11. Maybe that means it's
prohibited?

On the other hand, casting a non-const int to a non-const int or
casting a const int to a const int, does not involve a conversion.

By the way, you can still cast a non-const int to a const int by
reference:

int test1 = 5;
const int test2 = const_cast<const int &> (test1);

Gennaro Prota

unread,
Jan 11, 2007, 5:23:13 PM1/11/07
to
X-Replace-Address

Indeed, and there's an explicit note to that effect: "Subject to the


restrictions in this section, an expression may be cast to its own

type using a const_cast operator". The problem is elsewhere: if you
read very carefully the whole paragraph you'll see that (leaving out
"void" and other details which don't apply in your case) the target
type can only be a pointer-to-object, reference-to-object or
pointer-to-data-member type.

___
\|||/ Gennaro Prota - For hire
(o o) https://sourceforge.net/projects/breeze/
--ooO-(_)-Ooo----- (to mail: name _ surname / yaho ! com)

Hyman Rosen

unread,
Jan 11, 2007, 5:25:17 PM1/11/07
to
Alex Howlett wrote:
> Conversions that can be performed explicitly using
> const_cast are listed below. No other conversion shall be performed
> explicitly using const_cast.
>
> I read through the whole section and I don't see any restrictions on
> casting an expression to its own type.

You quoted the restriction yourself. Unless the cast you want is one of
the ones listed in the section (and in fact it isn't) you can't do it.

Alex Howlett

unread,
Jan 11, 2007, 5:38:30 PM1/11/07
to
Gennaro Prota pretended :

> Indeed, and there's an explicit note to that effect: "Subject to the
> restrictions in this section, an expression may be cast to its own
> type using a const_cast operator". The problem is elsewhere: if you
> read very carefully the whole paragraph you'll see that (leaving out
> "void" and other details which don't apply in your case) the target
> type can only be a pointer-to-object, reference-to-object or
> pointer-to-data-member type.

I see that it discusses rules for situations in which the target type
can only be a pointer-to-object, reference-to-object, or
pointer-to-data-member type. I do not see where it says that these are
the only allowed target types.

Alex Howlett

unread,
Jan 11, 2007, 5:47:40 PM1/11/07
to
Hyman Rosen brought next idea :

> You quoted the restriction yourself. Unless the cast you want is one of
> the ones listed in the section (and in fact it isn't) you can't do it.

1. The note is listed in the section below the restriction I quoted.
Doesn't that mean it counts as a cast that's listed in the section?

2. Regardless of that, here's the restriction again:

"Conversions that can be performed explicitly using const_cast are
listed below. No other conversion shall be performed explicitly using
const_cast."

It simply says that the conversions listed in the section are the only
conversions allowed. Seeing as how casting an expression to its own
type does not involve a conversion, I don't see how it applies

Hyman Rosen

unread,
Jan 12, 2007, 11:47:25 AM1/12/07
to
Alex Howlett wrote:
> 1. The note is listed in the section below the restriction I quoted.
> Doesn't that mean it counts as a cast that's listed in the section?

No, since notes aren't normative.

> Seeing as how casting an expression to its own
> type does not involve a conversion, I don't see how it applies

You're splitting hairs. A "conversion" just means the result of
applying the cast operator. If it meant what you say it means,
then the note would be meaningless. What would "subject to the
restrictions" mean if a const_cast to the identical type was
always legal?

Alex Howlett

unread,
Jan 12, 2007, 12:31:12 PM1/12/07
to
Hyman Rosen explained on 1/11/2007 :

> Alex Howlett wrote:
>> 1. The note is listed in the section below the restriction I quoted.
>> Doesn't that mean it counts as a cast that's listed in the section?
>
> No, since notes aren't normative.

Other than 17.3.1.1 (which only applies to the standard library stuff),
where does it say that notes are non-normative?

>
>> Seeing as how casting an expression to its own
>> type does not involve a conversion, I don't see how it applies
>
> You're splitting hairs. A "conversion" just means the result of
> applying the cast operator. If it meant what you say it means,
> then the note would be meaningless. What would "subject to the
> restrictions" mean if a const_cast to the identical type was
> always legal?

Where does it say that a conversion, in this context, just means the
result of applying the cast operator? It certainly doesn't mean that
in the part about standard conversions.

If "conversion" means what I say it means, the not would not
necessarily be meaningless. Because the note doesn't say cv-qualified
type, it could mean this:
---------------------------


2. [Note: Subject to the restrictions in this section, an expression

may be cast to its own type using a const_cast operator. (regardless of
cv-qualification) --end note]
---------------------------

In which case, one of the restrictions that would apply would be:
---------------------------
12. [Note: Some conversions which involve only changes in
cv-qualification cannot be done using const_cast. For instance,
conversions between pointers to functions are not covered because such
conversions lead to values whose use causes undefined behavior. For
the same reasons, conversions between pointers to member functions, and
in particular, the conversion from a pointer to a const member function
to a pointer to a non-const member function, are not covered. --end
note]
---------------------------

Or if notes are non-normative, as you claim, this would be the
restriction that applies:
---------------------------


Conversions that can be performed explicitly using const_cast are
listed below. No other conversion shall be performed explicitly using
const_cast.

---------------------------

It would restrict the casting of an expression to its own type to
situations in which the cv-qualifications also matched (because if the
cv-qualifications match, there's no conversion involved).

Pete Becker

unread,
Jan 12, 2007, 1:08:22 PM1/12/07
to
Alex Howlett wrote:
>
> Other than 17.3.1.1 (which only applies to the standard library stuff),
> where does it say that notes are non-normative?
>

ISO rules. Headings, footnotes, notes, and examples are not normative.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)

Alex Howlett

unread,
Jan 12, 2007, 1:24:16 PM1/12/07
to
on 1/12/2007, Pete Becker supposed :

> Alex Howlett wrote:
>>
>> Other than 17.3.1.1 (which only applies to the standard library stuff),
>> where does it say that notes are non-normative?
>>
>
> ISO rules. Headings, footnotes, notes, and examples are not normative.

Thanks. Where is this documented? I'd like to read up on these rules?

Pete Becker

unread,
Jan 12, 2007, 2:47:26 PM1/12/07
to
Alex Howlett wrote:
> on 1/12/2007, Pete Becker supposed :
>> Alex Howlett wrote:
>>>
>>> Other than 17.3.1.1 (which only applies to the standard library
>>> stuff), where does it say that notes are non-normative?
>>>
>>
>> ISO rules. Headings, footnotes, notes, and examples are not normative.
>
> Thanks. Where is this documented? I'd like to read up on these rules?
>

http://www.standardsinfo.net/isoiec/refpub.html, then download "ISO/IEC
Directives - Part 2. Rules for the structure and drafting of
International Standards". The content is even more boring than the title.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)

---

Alex Howlett

unread,
Jan 12, 2007, 5:28:02 PM1/12/07
to
Pete Becker expressed precisely :

> Alex Howlett wrote:
>> on 1/12/2007, Pete Becker supposed :
>>> Alex Howlett wrote:
>>>>
>>>> Other than 17.3.1.1 (which only applies to the standard library stuff),
>>>> where does it say that notes are non-normative?
>>>>
>>>
>>> ISO rules. Headings, footnotes, notes, and examples are not normative.
>>
>> Thanks. Where is this documented? I'd like to read up on these rules?
>>
>
> http://www.standardsinfo.net/isoiec/refpub.html, then download "ISO/IEC
> Directives - Part 2. Rules for the structure and drafting of International
> Standards". The content is even more boring than the title.

Thanks. That's what I needed. The content isn't boring if I'm
interested in it. =)

Jim Langston

unread,
Jan 14, 2007, 11:17:17 AM1/14/07
to
"Alex Howlett" <a.l_e.x_AT.s_u.n_c.h_o.D@T_c.o_m> wrote in message
news:mn.5bfd7d717...@Tc.om...

Oh, so that's the solution to the OP's problem.

int main ()


{
const int test1 = 5;

const int test2 = const_cast<const int&> (test1);

Martin Vejnár

unread,
Jan 14, 2007, 11:18:38 AM1/14/07
to
Alex Howlett wrote:
> The compiler I use (Visual C++ 2005) will not compile the following code:

Neither will Comeau.

> ----------------------------------
> int main (int argc, char * argv[])
> {
> const int test1 = 5;
> const int test2 = const_cast<const int> (test1);
>
> return 0;
> }
> ----------------------------------
> Error 1 error C2440: 'const_cast' : cannot convert from 'const
> int' to 'int' j:\test\main.cpp 4
> ----------------------------------
>
> So I looked to the standard and found that section 5.2.11 had this to
> say this about const_cast:
>

[snip]


> Conversions that can be performed explicitly using const_cast are
> listed below. No other conversion shall be performed explicitly using
> const_cast.

The section you mention enumerates all use cases in which const_cast can
be used -- all of them involve either pointers or references. It is not
legal to cast 'const int' to a 'const int' via const_cast.

> 2. [Note: Subject to the restrictions in this section, an expression may
> be cast to its own type using a const_cast operator. --end note]

Indeed, the note is misleading.

--
Martin

Alex Howlett

unread,
Jan 14, 2007, 3:29:54 PM1/14/07
to
Jim Langston wrote :

Nope. This does not solve my original problem. My original problem is
that you can't do this:

const_cast<const int> (test)

When test is a const int.

What I'm trying to do is make compilation fail if an object is not the
type I think it is. I want to be able to shut down the standard
conversions.

So this is the functionality I want:

int main (int argc, char * argv[])
{

const int test = five;

const_cast<const short &> (test); // Should fail and does.
const_cast<short &> (test); // Should fail and does.

const_cast<const int &> (test); // Should succeed and does.
const_cast<int &> (test); // Should succeed and does.

const_cast<const short> (test); // Should fail and does.
const_cast<short> (test); // Should fail and does.

const_cast<const int> (test); // *Should succeed but doesn't.
const_cast<int> (test); // Should fail and does.
}

I want to create a template function like this one:

template <class T, T val>
void TYPES_MATCH () throw()
{
const_cast<T> (val);
}

whose sole purpose is to kill the compilation if val isn't of type T.
In this case, I can't cast by reference because it would involve
creating a reference to a compile-time constant. So I need to do it by
value.

>From reading the standard it looks to me as if this is perfectly legal
and nobody has yet pointed out any language to the contrary.

Greg Herlihy

unread,
Jan 14, 2007, 9:36:20 PM1/14/07
to
Alex Howlett wrote:
> Nope. This does not solve my original problem. My original problem is
> that you can't do this:
>
> const_cast<const int> (test)
>
> When test is a const int.

The const_cast operator allows a program to perform non-const
operations upon an object declared as const (note that if the object so
accessed is defined as const then the effect of performing a non-const
operation upon the object is undefined). Therefore, since "const int"
describes a type - and not an object - the cast specified,
const_cast<const int>, makes no sense in terms of const_cast's
operation.

There is nothing to prevent the program from implementing its own
"cast" operator that does interpret the type argument as an object
specifier. This custom cast could cause a compile-time error whenever
the "cast" type and const-qualification specified by the program
differed from the type or const qualification of its argument:

// helper template to compare types

template <class T1, class T2>
struct same_type
{
static const bool value = false;
};

template <class T>
struct same_type<T, T>
{
static const bool value = true;
};

template <bool B>
struct no_cast{};

// operator() defined only for no_cast<true>

template <>
struct no_cast< true >
{
template <class T>
T operator()( T t) const
{
return t;
}
};

// fails if types disagree because
// no_cast<false>::operator()() is not defined

template< class T1, class T2>
inline T1
Check_Type( T2& t )
{
return no_cast< same_type<T1, T2>::value >()( t );
}

int main()
{
int five = 5;
int test = five;
const int kTest = five;

Check_Type< const short >( test ); // error
Check_Type< short > ( test ); // error
Check_Type< const int > ( test ); // error
Check_Type< int > ( test ); // OK

Check_Type< const short >( kTest ); // error
Check_Type< short > ( kTest ); // error
Check_Type< const int > ( kTest ); // OK
Check_Type< int > ( kTest ); // error
}

Greg

Alex Howlett

unread,
Jan 15, 2007, 1:00:17 AM1/15/07
to
Greg Herlihy presented the following explanation :

>
> The const_cast operator allows a program to perform non-const
> operations upon an object declared as const (note that if the object so
> accessed is defined as const then the effect of performing a non-const
> operation upon the object is undefined). Therefore, since "const int"
> describes a type - and not an object - the cast specified,
> const_cast<const int>, makes no sense in terms of const_cast's
> operation.
>
> There is nothing to prevent the program from implementing its own
> "cast" operator that does interpret the type argument as an object
> specifier. This custom cast could cause a compile-time error whenever
> the "cast" type and const-qualification specified by the program
> differed from the type or const qualification of its argument:
>
> Greg
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

You're a genius! Thank you so much! When I asked for help on the MSDN
forums I was presented only with these two alternatives:

1. Use boost's compile-time Assert to compare the sizes of the two
types.
2. Increase the compiler warning level to catch standard conversions.

Now I can do it the proper way! I never realized you could turn one
template parameter into a copy of the other one like that.

But it doesn't change the fact that the standard seems to allow
const_casting an expression to its own type. It does change the fact
of me caring. =)

Alex Howlett

unread,
Jan 15, 2007, 2:33:44 AM1/15/07
to
Martin Vejnár used his keyboard to write :

> Alex Howlett wrote:
>> Conversions that can be performed explicitly using const_cast are
>> listed below. No other conversion shall be performed explicitly using
>> const_cast.
>
> The section you mention enumerates all use cases in which const_cast can be
> used -- all of them involve either pointers or references. It is not legal to
> cast 'const int' to a 'const int' via const_cast.
>

Nope. It only says that the *conversions* that can be performed

explicitly using const_cast are listed below.

Casting an expression to its own type does not involve a conversion.

Greg Herlihy

unread,
Jan 15, 2007, 2:34:50 AM1/15/07
to
Alex Howlett wrote:
> Nope. This does not solve my original problem. My original problem is
> that you can't do this:
>
> const_cast<const int> (test)
>
> When test is a const int.

The const_cast operator allows a program to perform non-const


operations upon an object declared as const (note that if the object so
accessed is defined as const then the effect of performing a non-const
operation upon the object is undefined). Therefore, since "const int"
describes a type - and not an object - the cast specified,
const_cast<const int>, makes no sense in terms of const_cast's
operation.

There is nothing to prevent the program from implementing its own
"cast" operator that does interpret the type argument as an object
specifier. This custom cast could cause a compile-time error whenever
the "cast" type and const-qualification specified by the program
differed from the type or const qualification of its argument:

// helper template to compare types

Greg

---

Francis Glassborow

unread,
Jan 15, 2007, 10:13:27 AM1/15/07
to
In article <1168827590....@s34g2000cwa.googlegroups.com>, Greg
Herlihy <gre...@pacbell.net> writes

>The const_cast operator allows a program to perform non-const
>operations upon an object declared as const (note that if the object so
>accessed is defined as const then the effect of performing a non-const
>operation upon the object is undefined). Therefore, since "const int"
>describes a type - and not an object - the cast specified,
>const_cast<const int>, makes no sense in terms of const_cast's
>operation.

I am finding your use of 'declared' and 'defined' more than a little
confusing.

const_cast<> is only effectively applicable to references and pointers
because those can refer(point) to an object that is differently
qualified.

It is normal that const_cast<> is used to strip some or all of the cv
qualifiers but can certainly be used to add them (in which case, it can
generally be safely applied to an object rather than to just a
reference or pointer.

I think that another way of looking at this is to say that const_cast<>
results in undefined behaviour if used to remove a top level cv
qualifier.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

Martin Vejnár

unread,
Jan 15, 2007, 12:05:06 PM1/15/07
to
Alex Howlett wrote:
> Martin Vejnár used his keyboard to write :
>> Alex Howlett wrote:
>>> Conversions that can be performed explicitly using const_cast are
>>> listed below. No other conversion shall be performed explicitly using
>>> const_cast.
>>
>> The section you mention enumerates all use cases in which const_cast
>> can be used -- all of them involve either pointers or references. It
>> is not legal to cast 'const int' to a 'const int' via const_cast.
>>
>
> Nope. It only says that the *conversions* that can be performed
> explicitly using const_cast are listed below.
>
> Casting an expression to its own type does not involve a conversion.

Even if that were true, const_cast<const int>(v) still couldn't be used
reliably -- while the type of the expression is guaranteed to be 'const
int' (as specified in the first sentence of 5.2.11/1), its value is
undefined.

--
Martin

Kri¨tof ´elechovski

unread,
Jan 15, 2007, 11:39:41 PM1/15/07
to

> You're a genius! Thank you so much! When I asked for help on the MSDN
> forums I was presented only with these two alternatives:
>
> 1. Use boost's compile-time Assert to compare the sizes of the two types.
> 2. Increase the compiler warning level to catch standard conversions.
>
> Now I can do it the proper way! I never realized you could turn one
> template parameter into a copy of the other one like that.
>

3. b = *(0? (type_of_b const *) 0: &a);
You can wrap this expression in a macro or in a template inline function.
It is simpler in that it does not require the compiler to support partial
specialization.

Chris

Clark S. Cox III

unread,
Jan 16, 2007, 11:39:45 AM1/16/07
to
Alex Howlett wrote:
> Martin Vejnár used his keyboard to write :
>> Alex Howlett wrote:
>>> Conversions that can be performed explicitly using const_cast are
>>> listed below. No other conversion shall be performed explicitly using
>>> const_cast.
>>
>> The section you mention enumerates all use cases in which const_cast
>> can be used -- all of them involve either pointers or references. It
>> is not legal to cast 'const int' to a 'const int' via const_cast.
>>
>
> Nope. It only says that the *conversions* that can be performed
> explicitly using const_cast are listed below.
>
> Casting an expression to its own type does not involve a conversion.

It certainly does. It involves the lvalue-to-rvalue conversion.


--
Clark S. Cox III
clar...@gmail.com

0 new messages