While reading about a proposal for adding a const-propagating wrapper to the standard library (doc. no. N4388), I bumped into the example given in the paper:
#include <memory>
#include <iostream>
struct A
{
void bar() const
{
std::cout << "A::bar (const)" << std::endl;
}
void bar()
{
std::cout << "A::bar (non-const)" << std::endl;
}
};
struct B
{
B() : m_ptrA(std::make_unique<A>()) {}
void foo() const
{
std::cout << "B::foo (const)" << std::endl;
m_ptrA->bar(); // calls A::bar() (non-const)
// const_cast<const std::unique_ptr<A>>(m_ptrA)->bar(); // how to call the A::bar() const?
}
void foo()
{
std::cout << "B::foo (non-const)" << std::endl;
m_ptrA->bar();
}
std::unique_ptr<A> m_ptrA;
};
int main()
{
const B const_b;
const_b.foo();
}
which outputs:
B::foo (const)
A::bar (non-const)
I understand why this happens. Even if the pointer is const
, the object it points to is non-const, so indeed the non-const member function A::bar
is called (this is the whole point of the proposal in the paper, to avoid this seemingly awkward situation and propagate const
via a wrapper). Furthermore, they say that to avoid this situation, once can const_cast
the pointer m_ptrA
in B::foo() const
, so it calls the desired A::bar() const
.
I tried countless combinations but frankly I don't know how to const_cast
the unique_ptr
. Namely, how can I enforce in B::foo() const
the "right" call to A::bar() const
via the m_ptrA
? (see also the comment in the code if it's not entirely clear what I want).
You need to const-cast the stored pointer, not unique_ptr
:
const_cast<const A*>(m_ptrA.get())->bar();
const_cast<const A&>(*m_ptrA).bar();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With