----------------------------------
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 ]
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);
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)
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.
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.
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
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?
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).
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)
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)
---
Thanks. That's what I needed. The content isn't boring if I'm
interested in it. =)
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);
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
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.
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
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. =)
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.
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
---
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
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
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
It certainly does. It involves the lvalue-to-rvalue conversion.
--
Clark S. Cox III
clar...@gmail.com