samedi 14 mars 2020

propagate_const of const unique_ptr

The following example is taken from cppreference:

#include <iostream>
#include <memory>
#include <experimental/propagate_const>

struct X
{
    void g() const { std::cout << "g (const)\n"; }
    void g() { std::cout << "g (non-const)\n"; }
};

struct Y
{
    Y() : m_ptrX(std::make_unique<X>()) { }

    void f() const
    {
        std::cout << "f (const)\n";
        m_ptrX->g();
    }

    void f()
    {
        std::cout << "f (non-const)\n";
        m_ptrX->g();
    }

    std::experimental::propagate_const<std::unique_ptr<X>> m_ptrX;
};

int main()
{
    Y y;
    y.f();

    const Y cy;
    cy.f();
}

I want to further ensure the pointer (m_ptrX) address is not modifiable, so I changed the declaration to

std::experimental::propagate_const<const std::unique_ptr<X>> m_ptrX;

But it doesn't work, gcc 9 reports the following error (see here for detail)

g++ -std=c++2a -pthread  -O2 -Wall -Wextra -pedantic -pthread -pedantic-errors main.cpp -lm  -latomic -lstdc++fs  && ./a.out

In file included from main.cpp:3:

/usr/local/include/c++/9.2.0/experimental/propagate_const: In instantiation of 'constexpr std::experimental::fundamentals_v2::propagate_const<_Tp>::element_type* std::experimental::fundamentals_v2::propagate_const<_Tp>::get() [with _Tp = const std::unique_ptr<X>; std::experimental::fundamentals_v2::propagate_const<_Tp>::element_type = X]':

/usr/local/include/c++/9.2.0/experimental/propagate_const:205:13:   required from 'constexpr std::experimental::fundamentals_v2::propagate_const<_Tp>::element_type* std::experimental::fundamentals_v2::propagate_const<_Tp>::operator->() [with _Tp = const std::unique_ptr<X>; std::experimental::fundamentals_v2::propagate_const<_Tp>::element_type = X]'

main.cpp:24:15:   required from here

/usr/local/include/c++/9.2.0/experimental/propagate_const:225:25: error: invalid conversion from 'const element_type*' {aka 'const X*'} to 'std::experimental::fundamentals_v2::propagate_const<const std::unique_ptr<X> >::element_type*' {aka 'X*'} [-fpermissive]

  225 |  return __to_raw_pointer(_M_t);

      |         ~~~~~~~~~~~~~~~~^~~~~~

      |                         |

      |                         const element_type* {aka const X*}

So what is the correct way to achieve the effect, assuming I don't want to implement a template like immutable_unique_ptr.

Aucun commentaire:

Enregistrer un commentaire