Const_cast as undefined behavior?

Discussion in 'C++' started by Nephi Immortal, Jan 9, 2013.

  1. Please check to make sure if my code is safe since I chose to define only one class instead of two classes as const class and non-const class. Are you positive sure if undefined behavior does not occur? I am told that if I declare const_cast before undefined behavior will occur.

    Is copy constructor in class Y safe?


    class Y;

    class X
    {
    friend class Y;

    public:
    X( int data1, int data2 );
    Y Get() const;
    Y Set();

    private:
    int data1;
    int data2;
    };

    class Y
    {
    public:
    Y( X& p );
    Y( const Y& r );

    int Value1() const;
    void Value1( int data );

    int Value2() const;
    void Value2( int data );

    private:
    X& pX;
    };

    X::X( int data1, int data2 ) : data1( data1), data2( data2 )
    {
    }

    Y X::Get() const
    {
    return Y( const_cast< X& >( *this ));
    }

    Y X::Set()
    {
    return Y( *this );
    }

    Y::Y( X& p ) : pX( p )
    {
    }

    Y::Y( const Y& r ) : pX( r.pX )
    {
    }

    int Y::Value1() const
    {
    return pX.data1;
    }

    void Y::Value1( int data )
    {
    pX.data1 = data;
    }

    int Y::Value2() const
    {
    return pX.data2;
    }

    void Y::Value2( int data )
    {
    pX.data2 = data;
    }

    int main()
    {
    int number1 = 0, number2 = 0;

    // const X x( 5, 10 );
    X x( 5, 10 );

    number1 = x.Get().Value1();
    number2 = x.Get().Value2();

    x.Set().Value1( 50 ); // error if you declare const X x( 5, 10 )
    x.Set().Value2( 100 ); // error if you declare const X x( 5, 10 )

    number1 = x.Get().Value1();
    number2 = x.Get().Value2();

    return 0;
    }
     
    Nephi Immortal, Jan 9, 2013
    #1
    1. Advertising

  2. Nephi Immortal <> wrote:
    > Please check to make sure if my code is safe since I chose to define only
    > one class instead of two classes as const class and non-const class. Are
    > you positive sure if undefined behavior does not occur? I am told that
    > if I declare const_cast before undefined behavior will occur.
    >
    > Is copy constructor in class Y safe?
    >
    >
    > class Y;
    >
    > class X
    > {
    > friend class Y;
    >
    > public:
    > X( int data1, int data2 );
    > Y Get() const;
    > Y Set();
    >
    > private:
    > int data1;
    > int data2;
    > };
    >
    > class Y
    > {
    > public:
    > Y( X& p );
    > Y( const Y& r );
    >
    > int Value1() const;
    > void Value1( int data );
    >
    > int Value2() const;
    > void Value2( int data );
    >
    > private:
    > X& pX;
    > };
    >
    > X::X( int data1, int data2 ) : data1( data1), data2( data2 )
    > {
    > }
    >
    > Y X::Get() const
    > {
    > return Y( const_cast< X& >( *this ));
    > }
    >
    > Y X::Set()
    > {
    > return Y( *this );
    > }
    >
    > Y::Y( X& p ) : pX( p )
    > {
    > }
    >
    > Y::Y( const Y& r ) : pX( r.pX )
    > {
    > }
    >
    > int Y::Value1() const
    > {
    > return pX.data1;
    > }
    >
    > void Y::Value1( int data )
    > {
    > pX.data1 = data;
    > }
    >
    > int Y::Value2() const
    > {
    > return pX.data2;
    > }
    >
    > void Y::Value2( int data )
    > {
    > pX.data2 = data;
    > }
    >
    > int main()
    > {
    > int number1 = 0, number2 = 0;
    >
    > // const X x( 5, 10 );
    > X x( 5, 10 );
    >
    > number1 = x.Get().Value1();
    > number2 = x.Get().Value2();
    >
    > x.Set().Value1( 50 ); // error if you declare const X x( 5, 10 )
    > x.Set().Value2( 100 ); // error if you declare const X x( 5, 10 )
    >
    > number1 = x.Get().Value1();
    > number2 = x.Get().Value2();
    >
    > return 0;
    > }


    Const_casting a const object to a non-const reference is undefined
    behavior. That means, the following (valid) snippet triggers undefined
    behavior:

    const X x(5,10);
    int a = x.Get().value1();

    In practice, this will probably work everywhere, since you implicitly cast
    it immediately back to const X& when calling value1().

    The real problem in your code is, that the following will compile without
    errors:

    const X x(5,10);
    x.Get().value1(7);

    This is "real" undefined behavior and confusing anyway. Consider the
    following:

    X x(5,10);
    x.Set().value1(4);
    x.Get().value1(4); // compiles and has the same effect as the line before.

    The problem is, that you never ever have a const Y object, so the const
    qualifier on Y::value1/2() is basically useless.

    Now you can say that this ok because noone will ever do such a thing. I
    don't agree, but if you do, then I have a solution to make at least the
    non-pathologic cases free from undefined behavior:

    class Y
    {
    public:
    Y( const X& p ); // changed to const
    //...
    private:
    const X& pX; // changed to const
    };

    // ...

    void Y::Value1( int data )
    {
    const_cast<X&>(pX).data1 = data; // cast to non-const
    }

    void Y::Value2( int data )
    {
    const_cast<X&>(pX).data2 = data; // cast to non-const
    }

    Now I wonder what you actually want to achieve. What is the benefit over
    some simple SetValue1()/GetValue1() methods directly in X? Those are safer,
    simpler, and less confusing.

    It looks even almost the same:
    x.Set().value1(7);
    int i = x.Get().value1();
    vs.
    x.SetValue1(7);
    int i = x.GetValue1();

    Are you trying to create some sort of EDSL? Or C#-like property syntax?

    Tobi
     
    Tobias Müller, Jan 9, 2013
    #2
    1. Advertising

  3. On 1/8/2013 7:55 PM, Nephi Immortal wrote:
    > Please check to make sure if my code is safe since I chose to define only one class instead of two classes as const class and non-const class. Are you positive sure if undefined behavior does not occur? I am told that if I declare const_cast before undefined behavior will occur.


    I'm not sure what you mean by "declare const_cast", since it doesn't
    seem to make much sense. You can't declare `const_cast`.

    Anyway, `const_cast` never produces undefined behavior. It can serve as
    a tool that can help you to run into undefined behavior, since you can
    use it to cast away constness from a const object and then attempt to
    modify it. But `const_cast` itself does not produce undefined behavior.

    In short, attempting to modify a const object causes undefined behavior.
    Casting away constness by itself does not cause undefined behavior.

    > Is copy constructor in class Y safe?


    What do you mean by "safe"? There's nothing wrong with the copy
    constructor in your class `Y`. And there's nothing remarkable about it.
    In fact, you don't even have to write that copy constructor explicitly,
    since your explicit version does exactly the same thing as the
    implicitly generated version would do.

    Meanwhile, your code is not safe for reasons that have nothing to do
    with copy constructor of `Y`. You code is not safe because it can cast
    away the constness of `X` object in `X::Get`, pass it to the conversion
    constructor of `Y` and then attempt to modify that `X` object though
    method `Y::Value(int)`.

    >
    > int main()
    > {
    > int number1 = 0, number2 = 0;
    >
    > // const X x( 5, 10 );
    > X x( 5, 10 );
    >
    > number1 = x.Get().Value1();
    > number2 = x.Get().Value2();
    >
    > x.Set().Value1( 50 ); // error if you declare const X x( 5, 10 )
    > x.Set().Value2( 100 ); // error if you declare const X x( 5, 10 )


    If `x` was a constant object, this code produces undefined behavior in
    `Y::Value(int)`. If `x` was not a constant object, the code has defined
    behavior.

    But you know it already, judging by your comments. So, what is your
    question is supposed to be about?

    > number1 = x.Get().Value1();
    > number2 = x.Get().Value2();
    >
    > return 0;
    > }


    --
    Best regards,
    Andrey Tarasevich
     
    Andrey Tarasevich, Jan 9, 2013
    #3
  4. On 1/9/2013 6:03 AM, Tobias Müller wrote:
    >
    > Const_casting a const object to a non-const reference is undefined
    > behavior.


    No, it isn't. `const_cast` never produces undefined behavior.

    > That means, the following (valid) snippet triggers undefined
    > behavior:
    >
    > const X x(5,10);
    > int a = x.Get().value1();


    No, this snippet is perfectly fine. There's absolutely nothing undefined
    here. Even though this code casts away the constness of `x`, it makes no
    attempts to modify `x`. The code is ugly, but the behavior is defined.

    > In practice, this will probably work everywhere, since you implicitly cast
    > it immediately back to const X& when calling value1().
    >
    > The real problem in your code is, that the following will compile without
    > errors:
    >
    > const X x(5,10);
    > x.Get().value1(7);
    >
    > This is "real" undefined behavior and confusing anyway.


    This piece of code does indeed produce undefined behavior, because
    inside `Y::Value1(int)` it attempts to modify `x`, which happens to be a
    const object.

    --
    Best regards,
    Andrey Tarasevich
     
    Andrey Tarasevich, Jan 9, 2013
    #4
  5. Nephi Immortal

    Rui Maciel Guest

    Andrey Tarasevich wrote:

    > On 1/9/2013 6:03 AM, Tobias Müller wrote:
    >>
    >> Const_casting a const object to a non-const reference is undefined
    >> behavior.

    >
    > No, it isn't. `const_cast` never produces undefined behavior.


    The following is taken from the C++ standard [5.2.11 7]:

    <quote>
    Note: Depending on the type of the object, a write operation through the
    pointer, lvalue or pointer to data member resulting from a const_cast that
    casts away a const-qualifier72 may produce undefined behavior
    </quote>



    Rui Maciel
     
    Rui Maciel, Jan 9, 2013
    #5
  6. On 1/9/2013 4:42 PM, Rui Maciel wrote:
    > Andrey Tarasevich wrote:
    >
    >> On 1/9/2013 6:03 AM, Tobias Müller wrote:
    >>>
    >>> Const_casting a const object to a non-const reference is undefined
    >>> behavior.

    >>
    >> No, it isn't. `const_cast` never produces undefined behavior.

    >
    > The following is taken from the C++ standard [5.2.11 7]:
    >
    > <quote>
    > Note: Depending on the type of the object, a write operation through the
    > pointer, lvalue or pointer to data member resulting from a const_cast that
    > casts away a const-qualifier72 may produce undefined behavior
    > </quote>


    ".. a write operation through {blah} may produce undefined behavior",
    IOW, no write operation - no undefined behavior. The 'const_cast'
    itself does not represent a write operation.

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Jan 9, 2013
    #6
  7. Nephi Immortal

    Ian Collins Guest

    Rui Maciel wrote:
    > Andrey Tarasevich wrote:
    >
    >> On 1/9/2013 6:03 AM, Tobias Müller wrote:
    >>>
    >>> Const_casting a const object to a non-const reference is undefined
    >>> behavior.

    >>
    >> No, it isn't. `const_cast` never produces undefined behavior.

    >
    > The following is taken from the C++ standard [5.2.11 7]:
    >
    > <quote>
    > Note: Depending on the type of the object, a write operation through the
    > pointer, lvalue or pointer to data member resulting from a const_cast that
    > casts away a const-qualifier72 may produce undefined behavior
    > </quote>


    That doesn't contradict what was written. The write operation results
    in undefined behaviour, not the cast operation.

    --
    Ian Collins
     
    Ian Collins, Jan 9, 2013
    #7
  8. On 1/9/2013 1:42 PM, Rui Maciel wrote:
    >>
    >> No, it isn't. `const_cast` never produces undefined behavior.

    >
    > The following is taken from the C++ standard [5.2.11 7]:
    >
    > <quote>
    > Note: Depending on the type of the object, a write operation through the
    > pointer, lvalue or pointer to data member resulting from a const_cast that
    > casts away a const-qualifier72 may produce undefined behavior
    > </quote>


    As I stated in my answer, it is the attempt to modify a constant object
    ("... a write operation ...") that produces undefined behavior.

    `const_cast` itself is a way to create "the pointer, lvalue or pointer
    to data member" mentioned in the above quote. By itself it does not make
    any "write operations" through the resultant value. And it does not
    cause any undefined behavior.

    --
    Best regards,
    Andrey Tarasevich
     
    Andrey Tarasevich, Jan 9, 2013
    #8
  9. On Wednesday, January 9, 2013 8:03:38 AM UTC-6, Tobias Müller wrote:
    > Nephi Immortal <> wrote:
    >
    > > Please check to make sure if my code is safe since I chose to define only

    >
    > > one class instead of two classes as const class and non-const class. Are

    >
    > > you positive sure if undefined behavior does not occur? I am told that

    >
    > > if I declare const_cast before undefined behavior will occur.

    >
    > >

    >
    > > Is copy constructor in class Y safe?

    >
    > >

    >
    > >

    >
    > > class Y;

    >
    > >

    >
    > > class X

    >
    > > {

    >
    > > friend class Y;

    >
    > >

    >
    > > public:

    >
    > > X( int data1, int data2 );

    >
    > > Y Get() const;

    >
    > > Y Set();

    >
    > >

    >
    > > private:

    >
    > > int data1;

    >
    > > int data2;

    >
    > > };

    >
    > >

    >
    > > class Y

    >
    > > {

    >
    > > public:

    >
    > > Y( X& p );

    >
    > > Y( const Y& r );

    >
    > >

    >
    > > int Value1() const;

    >
    > > void Value1( int data );

    >
    > >

    >
    > > int Value2() const;

    >
    > > void Value2( int data );

    >
    > >

    >
    > > private:

    >
    > > X& pX;

    >
    > > };

    >
    > >

    >
    > > X::X( int data1, int data2 ) : data1( data1), data2( data2 )

    >
    > > {

    >
    > > }

    >
    > >

    >
    > > Y X::Get() const

    >
    > > {

    >
    > > return Y( const_cast< X& >( *this ));

    >
    > > }

    >
    > >

    >
    > > Y X::Set()

    >
    > > {

    >
    > > return Y( *this );

    >
    > > }

    >
    > >

    >
    > > Y::Y( X& p ) : pX( p )

    >
    > > {

    >
    > > }

    >
    > >

    >
    > > Y::Y( const Y& r ) : pX( r.pX )

    >
    > > {

    >
    > > }

    >
    > >

    >
    > > int Y::Value1() const

    >
    > > {

    >
    > > return pX.data1;

    >
    > > }

    >
    > >

    >
    > > void Y::Value1( int data )

    >
    > > {

    >
    > > pX.data1 = data;

    >
    > > }

    >
    > >

    >
    > > int Y::Value2() const

    >
    > > {

    >
    > > return pX.data2;

    >
    > > }

    >
    > >

    >
    > > void Y::Value2( int data )

    >
    > > {

    >
    > > pX.data2 = data;

    >
    > > }

    >
    > >

    >
    > > int main()

    >
    > > {

    >
    > > int number1 = 0, number2 = 0;

    >
    > >

    >
    > > // const X x( 5, 10 );

    >
    > > X x( 5, 10 );

    >
    > >

    >
    > > number1 = x.Get().Value1();

    >
    > > number2 = x.Get().Value2();

    >
    > >

    >
    > > x.Set().Value1( 50 ); // error if you declare const X x( 5, 10 )

    >
    > > x.Set().Value2( 100 ); // error if you declare const X x( 5, 10 )

    >
    > >

    >
    > > number1 = x.Get().Value1();

    >
    > > number2 = x.Get().Value2();

    >
    > >

    >
    > > return 0;

    >
    > > }

    >
    >
    >
    > Const_casting a const object to a non-const reference is undefined
    >
    > behavior. That means, the following (valid) snippet triggers undefined
    >
    > behavior:
    >
    >
    >
    > const X x(5,10);
    >
    > int a = x.Get().value1();
    >
    >
    >
    > In practice, this will probably work everywhere, since you implicitly cast
    >
    > it immediately back to const X& when calling value1().
    >
    >
    >
    > The real problem in your code is, that the following will compile without
    >
    > errors:
    >
    >
    >
    > const X x(5,10);
    >
    > x.Get().value1(7);
    >
    >
    >
    > This is "real" undefined behavior and confusing anyway. Consider the
    >
    > following:
    >
    >
    >
    > X x(5,10);
    >
    > x.Set().value1(4);
    >
    > x.Get().value1(4); // compiles and has the same effect as the line before..
    >
    >
    >
    > The problem is, that you never ever have a const Y object, so the const
    >
    > qualifier on Y::value1/2() is basically useless.
    >
    >
    >
    > Now you can say that this ok because noone will ever do such a thing. I
    >
    > don't agree, but if you do, then I have a solution to make at least the
    >
    > non-pathologic cases free from undefined behavior:
    >
    >
    >
    > class Y
    >
    > {
    >
    > public:
    >
    > Y( const X& p ); // changed to const
    >
    > //...
    >
    > private:
    >
    > const X& pX; // changed to const
    >
    > };
    >
    >
    >
    > // ...
    >
    >
    >
    > void Y::Value1( int data )
    >
    > {
    >
    > const_cast<X&>(pX).data1 = data; // cast to non-const
    >
    > }
    >
    >
    >
    > void Y::Value2( int data )
    >
    > {
    >
    > const_cast<X&>(pX).data2 = data; // cast to non-const
    >
    > }

    If all data members in this class are constant, and you want to modify someof them when necessary. The programmers always use const_cast since mutable did not exist in earlier C++ Compiler. They are able to use mutable so that they are not tempted to use const_cast by mistake.
    >
    >
    >
    > Now I wonder what you actually want to achieve. What is the benefit over
    >
    > some simple SetValue1()/GetValue1() methods directly in X? Those are safer,
    >
    > simpler, and less confusing.
    >
    >
    >
    > It looks even almost the same:
    >
    > x.Set().value1(7);
    >
    > int i = x.Get().value1();
    >
    > vs.
    >
    > x.SetValue1(7);
    >
    > int i = x.GetValue1();


    Both methods are your preferred choice. I choose to add proxy class with main class because Set() and Get() call proxy class’ member functions are easier to be readable than whole word and/or underscore. In other words, when you use Visual C++ and you type the dot (.) between class’ variable and member functions, the pop-up menu appears to the screen giving you many choices to select member functions rather than read each member functions from code.

    I use C++, but NOT C#. That is why I go to C++ newsgroups.


    >
    >
    >
    > Are you trying to create some sort of EDSL? Or C#-like property syntax?
    >
    >
    >
    > Tobi
     
    Nephi Immortal, Jan 10, 2013
    #9
  10. Nephi Immortal

    Rui Maciel Guest

    Andrey Tarasevich wrote:

    > As I stated in my answer, it is the attempt to modify a constant object
    > ("... a write operation ...") that produces undefined behavior.
    >
    > `const_cast` itself is a way to create "the pointer, lvalue or pointer
    > to data member" mentioned in the above quote. By itself it does not make
    > any "write operations" through the resultant value. And it does not
    > cause any undefined behavior.


    That's not right. What may lead to undefined behavior is having used
    const_cast to remove access restrictions which should always be there and
    should never be taken away. If the const qualifier isn't used irresponsibly
    then the compiler naturally catches the attempt to call non-const member
    functions on a const object, as is expected from him.

    Let's be honest here: if you one day stumbled on a bug caused by this sort
    of problem, you would never claim that the const_cast was perfectly fine,
    and that the entire problem was caused by how the "write operation" has been
    poorly designed so that it fails to work when its access restrictions were
    removed.


    Rui Maciel
     
    Rui Maciel, Jan 10, 2013
    #10
  11. Nephi Immortal

    Rui Maciel Guest

    Ian Collins wrote:

    > That doesn't contradict what was written. The write operation results
    > in undefined behaviour, not the cast operation.


    What leads to the undefined behavior is the removal of the safeguards
    against abusing that write operation. After intentionally removing a
    failsafe, if executing an operation, which by design should never be
    executed, happens to unleash havoc then it isn't possible to blame that
    operation for the problems. The responsibility lies nowhere else besides
    how the failsafe has been removed, and how that left the system in an
    unstable state.


    Rui Maciel
     
    Rui Maciel, Jan 10, 2013
    #11
  12. Nephi Immortal

    Ian Collins Guest

    Rui Maciel wrote:
    > Andrey Tarasevich wrote:
    >
    >> As I stated in my answer, it is the attempt to modify a constant object
    >> ("... a write operation ...") that produces undefined behavior.
    >>
    >> `const_cast` itself is a way to create "the pointer, lvalue or pointer
    >> to data member" mentioned in the above quote. By itself it does not make
    >> any "write operations" through the resultant value. And it does not
    >> cause any undefined behavior.

    >
    > That's not right.


    Oh yes it is!

    > What may lead to undefined behavior is having used
    > const_cast to remove access restrictions which should always be there and
    > should never be taken away.


    No it isn't.

    It's not uncommon to have to pass something like a string literal or the
    result of std::string's c_str() to a C function that (mis)uses char* for
    a parameter. One example that pops up a few times in my code base is
    the UNIX putenv() function.

    > If the const qualifier isn't used irresponsibly
    > then the compiler naturally catches the attempt to call non-const member
    > functions on a const object, as is expected from him.
    >
    > Let's be honest here: if you one day stumbled on a bug caused by this sort
    > of problem, you would never claim that the const_cast was perfectly fine,
    > and that the entire problem was caused by how the "write operation" has been
    > poorly designed so that it fails to work when its access restrictions were
    > removed.


    Some of us have to live with crusty C interfaces....

    --
    Ian Collins
     
    Ian Collins, Jan 10, 2013
    #12
  13. Nephi Immortal

    Rui Maciel Guest

    Victor Bazarov wrote:

    > ".. a write operation through {blah} may produce undefined behavior",
    > IOW, no write operation - no undefined behavior. The 'const_cast'
    > itself does not represent a write operation.


    The const_cast removes the qualifier which was put in place to ensure that
    the system was never left in an unstable state. Once the qualifier was
    removed, there is no guarantee that things won't start to blow up. In its
    nature, this is no different than intentionally writing on memory segments
    which weren't allocated and may or may not be a part of any other object.


    Rui Maciel
     
    Rui Maciel, Jan 10, 2013
    #13
  14. Nephi Immortal

    Ian Collins Guest

    Rui Maciel wrote:
    > Ian Collins wrote:
    >
    >> That doesn't contradict what was written. The write operation results
    >> in undefined behaviour, not the cast operation.

    >
    > What leads to the undefined behavior is the removal of the safeguards
    > against abusing that write operation. After intentionally removing a
    > failsafe, if executing an operation, which by design should never be
    > executed, happens to unleash havoc then it isn't possible to blame that
    > operation for the problems. The responsibility lies nowhere else besides
    > how the failsafe has been removed, and how that left the system in an
    > unstable state.


    See the example use of putenv() here:

    http://pubs.opengroup.org/onlinepubs/000095399/

    and make it work in C++ without copying the string literal. That's just
    one of many I come across most days....

    --
    Ian Collins
     
    Ian Collins, Jan 10, 2013
    #14
  15. Nephi Immortal

    Rui Maciel Guest

    Ian Collins wrote:

    >> What may lead to undefined behavior is having used
    >> const_cast to remove access restrictions which should always be there and
    >> should never be taken away.

    >
    > No it isn't.
    >
    > It's not uncommon to have to pass something like a string literal or the
    > result of std::string's c_str() to a C function that (mis)uses char* for
    > a parameter. One example that pops up a few times in my code base is
    > the UNIX putenv() function.


    The standard states quite clearly that it depends on both the object type
    and on the write operation. Using a const_cast doesn't always lead to
    undefined behavior. If it did then there would be no point in having it to
    begin with.

    If the const_cast is used to remove access restrictions which were put in
    place to ensure that the system remains stable, removing those access
    restrictions places the system in an unstable state. No one can blame an
    operation for a problem caused by eliminating the restrictions that were in
    place to make sure it would be impossible to perform.


    Rui Maciel
     
    Rui Maciel, Jan 10, 2013
    #15
  16. Nephi Immortal

    Rui Maciel Guest

    Ian Collins wrote:

    > See the example use of putenv() here:
    >
    > http://pubs.opengroup.org/onlinepubs/000095399/
    >
    > and make it work in C++ without copying the string literal. That's just
    > one of many I come across most days....


    The standard quite clearly states that it depends on the object type and the
    write operation.

    This is even more relevant in C++11, as since this standard revision the
    const qualifier defines the thread safety of an object. The standard states
    [17.6.5.9] the following:

    <quote>
    A C ++ standard library function shall not directly or indirectly modify
    objects (1.10) accessible by threads other than the current thread unless
    the objects are accessed directly or indirectly via the function’s non-
    const arguments, including this.
    </quote>


    By calling const_cast to cast away a const qualifier, you tell the compiler
    that thread-unsafe operations are actually thread safe. Then, when those
    operations are called, operations which otherwise would not be possible to
    call, nasty stuff happens.

    Here's Herb Sutter's presentation on this subject:

    http://channel9.msdn.com/posts/C-and-Beyond-2012-Herb-Sutter-You-dont-know-
    blank-and-blank

    you can watch from 10m30s to cut to the chase.


    Rui Maciel
     
    Rui Maciel, Jan 10, 2013
    #16
  17. Rui Maciel <> wrote:
    > Ian Collins wrote:
    >
    >> That doesn't contradict what was written. The write operation results
    >> in undefined behaviour, not the cast operation.

    >
    > What leads to the undefined behavior is the removal of the safeguards
    > against abusing that write operation. After intentionally removing a
    > failsafe, if executing an operation, which by design should never be
    > executed, happens to unleash havoc then it isn't possible to blame that
    > operation for the problems. The responsibility lies nowhere else besides
    > how the failsafe has been removed, and how that left the system in an
    > unstable state.


    Thanks for the pointer to the standard, my memories were wrong.

    Actually, I agree with Ian, the const_cast per se does not lead directly to
    undefined behavior. Just because it may lead to undefined behavior if
    sometimes in the future a programmer abuses it, it doesn't mean that it is
    undefined behavior now.

    Tobi
     
    Tobias Müller, Jan 10, 2013
    #17
  18. On Thu, 10 Jan 2013 02:02:11 +0000, Rui Maciel wrote:

    > Victor Bazarov wrote:
    >
    >> ".. a write operation through {blah} may produce undefined behavior",
    >> IOW, no write operation - no undefined behavior. The 'const_cast'
    >> itself does not represent a write operation.

    >
    > The const_cast removes the qualifier which was put in place to ensure
    > that the system was never left in an unstable state. Once the qualifier
    > was removed, there is no guarantee that things won't start to blow up.
    > In its nature, this is no different than intentionally writing on memory
    > segments which weren't allocated and may or may not be a part of any
    > other object.


    Do I understand you correctly that you are saying this gives UB:

    const char* my_strchr(const char* str, char c)
    {
    /* my replacement implementation of strchr(): */
    return str;
    }
    char* my_strchr(char* str, char c)
    {
    return cons_cast<char*>(my_strchr(cont_cast<const char*>(str), c));
    }

    Note that I use const_cast *twice* in the second function, one of them to
    remove a const-qualification.

    >
    >
    > Rui Maciel


    Bart v Ingen Schenau
     
    Bart van Ingen Schenau, Jan 10, 2013
    #18
  19. On 1/9/2013 5:43 PM, Rui Maciel wrote:
    > Andrey Tarasevich wrote:
    >
    >> As I stated in my answer, it is the attempt to modify a constant object
    >> ("... a write operation ...") that produces undefined behavior.
    >>
    >> `const_cast` itself is a way to create "the pointer, lvalue or pointer
    >> to data member" mentioned in the above quote. By itself it does not make
    >> any "write operations" through the resultant value. And it does not
    >> cause any undefined behavior.

    >
    > That's not right. What may lead to undefined behavior is having used
    > const_cast to remove access restrictions which should always be there and
    > should never be taken away.If the const qualifier isn't used irresponsibly
    > then the compiler naturally catches the attempt to call non-const member
    > functions on a const object, as is expected from him.


    That is probably very sound reasoning, but that is not how the language
    is defined. And the language has its reasons to be defined the way it is
    defined.

    In the current C++ language removing constness from an access path is a
    perfectly valid operation, which never causes undefined behavior, even
    if the object on the ather end of that access path is actually `const`.

    > Let's be honest here: if you one day stumbled on a bug caused by this sort
    > of problem, you would never claim that the const_cast was perfectly fine,
    > and that the entire problem was caused by how the "write operation" has been
    > poorly designed so that it fails to work when its access restrictions were
    > removed.


    Probably. But that's the reality of C++ programming.

    In any case, the matter of bad/good programming practices and the matter
    of formal language specifications are two different matters. And the
    concept of "undefined behavior" belongs to the realm of the latter.

    --
    Best regards,
    Andrey Tarasevich
     
    Andrey Tarasevich, Jan 10, 2013
    #19
  20. On 1/9/2013 5:56 PM, Rui Maciel wrote:
    > Ian Collins wrote:
    >
    >> That doesn't contradict what was written. The write operation results
    >> in undefined behaviour, not the cast operation.

    >
    > What leads to the undefined behavior is the removal of the safeguards
    > against abusing that write operation.


    Well, ultimately that's no different that stating the the very design of
    C++ language is what _really_ leads to all kinds of undefined behavior.
    And we have no shortage of individuals who just love to spread this sort
    of wisdom around various places on the net and outside of it.

    While this might be an interesting topic for some people, it is not
    really what the question is about.

    --
    Best regards,
    Andrey Tarasevich
     
    Andrey Tarasevich, Jan 10, 2013
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kaspar Minosiants

    [help] const_cast

    Kaspar Minosiants, Jul 21, 2003, in forum: C++
    Replies:
    2
    Views:
    444
    John Harrison
    Jul 21, 2003
  2. drowned

    const_cast question

    drowned, Aug 4, 2003, in forum: C++
    Replies:
    3
    Views:
    495
    Josephine Schafer
    Aug 4, 2003
  3. Simon Bailey

    const_cast undefined results

    Simon Bailey, Oct 12, 2004, in forum: C++
    Replies:
    6
    Views:
    580
    Ron Natalie
    Oct 13, 2004
  4. Mantorok Redgormor
    Replies:
    70
    Views:
    1,822
    Dan Pop
    Feb 17, 2004
  5. Alf P. Steinbach

    Re: plz xplain behavior of const_cast

    Alf P. Steinbach, Jan 5, 2012, in forum: C++
    Replies:
    8
    Views:
    247
    88888 Dihedral
    Jan 7, 2012
Loading...

Share This Page