static_cast taking away constness
Asked Answered
L

1

5

From my knowledge (and this topic: When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?) const_cast is the only cast that should be able to take away constness of a variable. However, when messing around with clang-6.0 and g++5.4.0 I stumbled upon a behaviour that would contradict the above. It seems static_cast does exactly the same job.

These main functions give the exact same results with both compilers:

test class definition

struct Base {
        Base() {
                std::cout << "Base::Base()\n";
        }
        void test() const {
                std::cout << "Base::test()\n";
        }

        void no_const() {
                std::cout << "Base::no_const()\n";
        }

        virtual ~Base() = default;
};

with const_cast

int main(void) {
        std::cout << "BEGIN\n";
        const Base b;
        const_cast<Base&>(b).no_const();

        std::cout << "END\n";
}

with static_cast

int main(void) {
        std::cout << "BEGIN\n";
        const Base b;
        static_cast<Base>(b).no_const();

        std::cout << "END\n";
}

Result:

BEGIN
Base::Base()
Base::no_const()
END

What gives?

Linders answered 25/8, 2018 at 21:24 Comment(1)
You are playing a sleight of hand. The two casts are dissimilar - one casts to Base& reference, the other to Base - this involves creating a temporary copy; it does not cast away constness from the original. If you try static_cast<Base&>(b), you'll get the error you've expected.Hathaway
C
9

Add a copy constructor definition for Base, it'll answer your question.

Base(Base const&) {
        std::cout << "Base::Base(Base const&)\n";
}

The output from your second example changes to

BEGIN
Base::Base()
Base::Base(Base const&)
Base::no_const()
END

Live demo


Attempt to cast away constness from b itself, and you'll see an error

static_cast<Base&>(b).no_const();
//              ^

error: invalid static_cast from type 'const Base' to type 'Base&'

  static_cast<Base&>(b).no_const();
Chesty answered 25/8, 2018 at 21:29 Comment(1)
Ah, the copy constructor - that's the building block I forgot. Shame on me! Thanks a lot!Lavellelaven

© 2022 - 2024 — McMap. All rights reserved.