I just discovered how easy it is to modify const objects without any const_cast
black magic. Consider:
#include <iostream>
class Test {
public:
Test(int v)
:m_val{ v },
m_ptr{ &m_val }
{}
int get() const { return m_val; }
void set(int v) const { *m_ptr = v; }
private:
int m_val;
int* m_ptr;
};
int main()
{
const Test t{ 10 };
std::cout << t.get() << '\n';
t.set(0);
std::cout << t.get() << '\n';
return 0;
}
Recent versions of Clang, GCC, and MSVC don't show any warning and produce expected output:
10 0
Is this well defined behavior according to the current standard? If it's undefined what if m_val
was of type std::aligned_storage_t<sizeof(int), alignof(int)>
and constructor new
'ed int
in it? I believe it's pretty common case when it comes to small buffer optimizations.
Edit
Thanks, it seems that it's just another way to shoot yourself in a foot. What's troubling it seems that this:
struct Test2 {
int i;
void operator()() { ++i; }
};
const std::function<void()> f{ Test2{ 10 } };
f();
is also undefined behavior when implementation chooses to store the Test2
object inside f
(and that's the case in libc++ and in Visual Studio)