Question about const_cast

Here's round two of my silly questions.
How come this compiles:
----------------------------------
int main (int argc, char * argv[])
{
const int test1 = 5;
const int test2 = const_cast<const int &> (test1);
 return 0;
}
----------------------------------
But this does not.
----------------------------------
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 definitely have the latest version of VC++ Express Edition this time.


Answer this question

Question about const_cast

  • ACCOUNTINGONLINE.US

    einaros wrote:

    It's not my intention to sound rude here, but I am getting somewhat tired of repeating myself. If you doubt my judgement, test other major (or minor) compilers -- they'll tell you exactly what I've been trying to.

    So you're saying that Visual C++ 2005 violates the standard, but it's ok because the other major compilers do it too


  • Colin Reid

     einaros wrote:

    You don't like that you can read the variable test1, or the fact that you can initialize the variable test2 A const value is read only. Those two lines does not enable anyone to change the value that is test1, and it does not enable anyone to change the value that is test2. Both variables are at two different memory locations, and changing one does not change the other.

    I'm not saying that those two lines enable anyone to change the value of test1.  What I'm saying is that I'm accidentally truncating the value of test1 when storing it in test2 and I want to prevent that from accidentally happening by using a const_cast.

     einaros wrote:

    If you initialize the test2 variable with the vlaue from test1, you will have two const variables, one double and one int. The const_cast is redundant.

    Yes.  I realize that, in this case, the const_cast is redundant, but it wouldn't be redundant if instead of casting from a double, I were casting from some typedef and I didn't know whether that typedef stood for an int or not.  The compiler would then catch the error at compile time.

     einaros wrote:

    I don't think that const_cast is the real issue at hand here.. You seem to slightly misinterpret what const variables are, and perhaps also the difference between values, pointers and references. How do you think that your first example may corrupt your application, or program flow

    I just want to prevent myself from accidentally assigning doubles to ints and similar things.


  • VarunR

    Nowhere is there a restriction that says the destination must be a pointer or reference.
  • m14cus

    Suncho wrote:
    Nowhere is there a restriction that says the exp ression must be a pointer or reference.

    No, it's slightly more complex. It specifies what is supposed to be possible, and that anything else isn't. And let me repeat this once more: it doesn't make sense for const_cast to allow casts of non-reference or non-pointer types, so it won't. It's really that simple. You are attempting to do something which borderlines whats possible, and you will simply have to live with the consequences.

    It's not my intention to sound rude here, but I am getting somewhat tired of repeating myself. If you doubt my judgement, test other major (or minor) compilers -- they'll tell you exactly what I've been trying to.



  • sandeep437

    Suncho wrote:

    I'm not saying that those two lines enable anyone to change the value of test1. What I'm saying is that I'm accidentally truncating the value of test1 when storing it in test2 and I want to prevent that from accidentally happening by using a const_cast.

    Ah, but that cannot be done through const_cast, or any other cast. What you can do, however, is either

    1. Enable level4 warnings, and the compiler setting which treats warnings as errors. This should cause an error with a message indicating that a truncation may occur.
    2. Use a compile time assert, such as boost.org's BOOST_STATIC_ASSERT macro. This can be used such as:

    BOOST_STATIC_ASSERT(sizeof(type1) == sizeof(type2));

    You can also see a blog post of mine, at http://einaros.livejournal.com/2530.html.



  • michaelp

     einaros wrote:

    Ah, but that cannot be done through const_cast

    Obviously it can.  I'm using it for that.  I'm just wondering why I have to cast it to a reference instead of to a value. 

     einaros wrote:

    Enable level4 warnings, and the compiler setting which treats warnings as errors. This should cause an error with a message indicating that a truncation may occur.

    This is all well and good as long as it's just me using the code, but I don't want everyone who uses my code to have to set the compiler warnings.

     einaros wrote:

    Use a compile time assert, such as boost.org's BOOST_STATIC_ASSERT macro. This can be used such as:

    BOOST_STATIC_ASSERT(sizeof(type1) == sizeof(type2));

    You can also see a blog post of mine, at http://einaros.livejournal.com/2530.html.

    Yeah.  I wrote my own compile-time assert that's a template rather than a macro.  But this won't work.  I'm trying to write portable code and who's to say that an int isn't the same size as a double   Or more importantly, I also want to prevent accidental assignments from float to int.

    Regardless of any of that, I already have the functionality I need with const_cast.  I just want to know why I have to cast to a reference.  That's all.


  • eldiener

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

    It's there, and I've highlighted the important part. It may be cast to its own type, as long as the destination is a pointer or reference.



  • jbwitt

    I'm not trying to use const_cast to cast away constness.  I'm trying to use it to cause the compiler to fail if I accidentally try to assign a variable of one type to a variable of another type.

    I don't like that you can do this:   

            const double test1 = 5.1;   // 5.1
            const int test2 = test1;    // The integer 5

    So I want to do this:

            const double test1 = 5.1    // 5.1
            const int test2 = const_cast<const int> (test1); // Error.

    But I want it to work ok when I do this:

            const int test1 = 5;   // The integer 5
            const int test2 = const_cast<const int> (test1); // Fine - The integer 5

    I'm fine with casting to a reference, but I'm curious to know why casting to a value doesn't work just as well.  

    The standard says that an exp_ression may be cast to its own type using a const_cast operator.  That's the functionality I was looking for.


  • Senthil.P

    Suncho wrote:

    Regardless of any of that, I already have the functionality I need with const_cast. I just want to know why I have to cast to a reference. That's all.

    Very well, I'll stop telling you it's bad practice, unintended use, and could possibly create unoptimized code. Just remember that your approach also breaks all perfectly good conversions, such as char to int, float to double as well as all implicit conversions of class types (though constructors, assignment operators and custom conversion operators).

    The error noted in your first post occurs because the standard forbids the use of const_cast with types that aren't either; pointers, references, pointer to member to an object type.



  • Dexterz

    To begin with the conclusion: Your second example is a by-value assignment, and there's no need to use const_cast to remove the constness off such.

    Consider the following

    const int x = 10;
    int y = x;

    x will be a constant variable in memory, to which the compiler will refuse to assign values. The variable is read only. When you assign this to the y variable, x's value is copied into a non-constant integer; obeying the read only constraint. After executing both lines, the 10 will exist in two different memory locations.

    Now consider:

    const int x = 10;
    int y = const_cast<const int&>(x);

    This will essentially do the same: at the end of the execution, two variables will exist in memory. Compared to the first example, however, a temporary integer reference is created on line two.

    const int& xref = x; // reference to x
    // ... is the same as ...
    const int& xref2 = const_cast<const int&>(x); // also a reference to x

    It makes no sense to do it, but the compiler happily compiles it, both in expanded version as this last example shows, and the temporary variable version you provided.

    Finally consider:

    const int x = 10;
    int y = const_cast<const int>(x);

    Will make so little sense, that the compiler simply refuses to do it. const_cast is defined and implemented to remove the constness off references and pointers, so the compile will fail if it's attempted used to provide values.

    What you can do with const_cast, or rather what it's designed to do (although the example is horrible with regard to const obeyance) is:

    const int x = 10;
    int& xref = const_cast<int&>(x);
    xref = 100; // change a const value through a non-const reference, *shudder*



  • renyx

    einaros wrote:

    Very well, I'll stop telling you it's bad practice, unintended use, and could possibly create unoptimized code. Just remember that your approach also breaks all perfectly good conversions, such as char to int, float to double as well as all implicit conversions of class types (though constructors, assignment operators and custom conversion operators).

    Thank you. I don't care about its "intended" use. I care about is what it does. Actually, I also want to break conversions from char to int and float to double. For my specific needs, these implicit conversions are not "perfectly good."

    einaros wrote:

    The error noted in your first post occurs because the standard forbids the use of const_cast with types that aren't either; pointers, references, pointer to member to an object type.

    That's interesting because I read that whole section on const_cast and I didn't see where it said that. Please show me. Thanks.


  • Bill Reiss

    Suncho wrote:

    I don't like that you can do this:

    const double test1 = 5.1; // 5.1
    const int test2 = test1; // The integer 5

    You don't like that you can read the variable test1, or the fact that you can initialize the variable test2 A const value is read only. Those two lines does not enable anyone to change the value that is test1, and it does not enable anyone to change the value that is test2. Both variables are at two different memory locations, and changing one does not change the other.

    Suncho wrote:

    So I want to do this:

    const double test1 = 5.1 // 5.1
    const int test2 = const_cast<const int> (test1); // Error.

    If you initialize the test2 variable with the vlaue from test1, you will have two const variables, one double and one int. The const_cast is redundant.

    I don't think that const_cast is the real issue at hand here.. You seem to slightly misinterpret what const variables are, and perhaps also the difference between values, pointers and references. How do you think that your first example may corrupt your application, or program flow



  • sravan195

    Conversions that can be performed explicitly using const_cast are listed
    below. No other conversion shall be performed explicitly using const_cast.
    [...]
    For two pointer types T1 and T2 where
    T1 is cv1 , 0 pointer to cv1 , 1 pointer to . . . cv1 ,n - 1 pointer to cv1 ,n T
    and
    T2 is cv2 , 0 pointer to cv2 , 1 pointer to . . . cv2 ,n - 1 pointer to cv2 ,n T
    [...]
    An lvalue of type T1 can be explicitly converted to an lvalue of type T2 using the cast
    const_cast<T2&> (where T1 and T2 are object types) if a pointer to T1 can be explicitly converted to
    the type pointer to T2 using a const_cast. The result of a reference const_cast refers to the original object.
    [...]
    For a const_cast involving pointers to data members, multi-level pointers to data members and multilevel
    mixed pointers and pointers to data members (4.4), the rules for const_cast are the same as those
    used for pointers
    [...]
    A null pointer value (4.10) is converted to the null pointer value of the destination type. The null member
    pointer value (4.11) is converted to the null member pointer value of the destination type.
    [...]

    And it goes on. The standard does not specify that const_casts between non-reference or non-pointer types should be possible. Why It doesn't make sense for const_cast to provide this functionality.



  • stratos13

    Oh.  In the draft that I have (2006-11-03), right below where it says this:
    -----------------------------------------
    No other conversions shall be performed explicitly using const_cast.
    -----------------------------------------

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

    Is that line not in the official version


  • Question about const_cast