如何通过std::unique_ptr成员调用其他类的const成员函数

7

在阅读一个向标准库添加常量传播包装器的提案时(文档编号:N4388),我遇到了论文中给出的例子:

#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();
}

输出如下:

B::foo (const)
A::bar (non-const)

我理解为什么会出现这种情况。即使指针是const,它所指向的对象仍然是非const的,因此实际上调用了非const成员函数A::bar(这就是论文提议的整个目的,通过包装器传播const来避免这种看似尴尬的情况)。此外,他们说为了避免这种情况,可以在B::foo() const中对指针m_ptrA进行const_cast,以调用所需的A::bar() const

我尝试了无数组合,但老实说我不知道如何const_cast unique_ptr。也就是说,在B::foo() const中,我该如何通过m_ptrA强制执行对A::bar() const的“正确”调用?(如果不完全清楚我的意思,请参见代码中的注释。)


2
static_cast<const Type&>(*ptr).method() - Tavian Barnes
1个回答

6

您需要对存储的指针进行const_cast,而不是使用 unique_ptr

const_cast<const A*>(m_ptrA.get())->bar();
const_cast<const A&>(*m_ptrA).bar();

谢谢,这确实有效。出于某种原因,我认为我可以直接在智能指针上使用const_cast,类似于shared_ptrstatic_pointer_cast。但你的解决方案可能是唯一的方法。 - vsoftco
@vsoftco const_cast 在智能指针上改变了智能指针的常量性,但是智能指针的 operator ->operator * 并不保留返回对象的常量性。这模仿了原始指针的行为。如果您需要保持常量性的指针,可以使用此实现 - StenSoft

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接