通过构造从结构到其指针和参考成员

Pass through constness from a struct to its pointer and reference members

本文关键字:指针 参考 成员 结构      更新时间:2023-10-16

我有一个带有指针的结构。我想做到这一点,所以如果结构实例是const,则无法修改其指针的内容。

struct Foo {};
struct Bar {
    Foo /*const goes here if `const Bar`*/ *foo;
};
void f(Bar& bar) {
    *bar.foo = Foo(); // OK
}
void g(const Bar& bar) {
    *bar.foo = Foo(); // OK - but should be error
}

是否有一种方法可以通过构造从结构到指针和参考成员?

封装在救援中!

只是通过接口访问Marshall:

struct Bar {
  Foo * getFoo() { return foo; }
  Foo const * getFoo() const { return foo; }
private:
  Foo *foo;
};
void f(Bar& bar) {
    *bar.getfoo() = Foo(); // OK
}
void g(const Bar& bar) {
    *bar.getfoo() = Foo(); // Error!
}

您正在与语言作斗争,不要那样做。就像在上游游泳一样 - 您只会疲倦,而不喜欢结果。

可以通过使用私人数据和成员函数来解决您的问题:

struct Foo {};
struct Bar {
   void reset() {
      *foo = Foo();
   }
private:
    Foo  *foo;
};
void f(Bar& bar) {
    bar.reset();   // OK
}
void g(const Bar& bar) {
    bar.reset();   // fails, as reset is not declared const
}

使const推动智能指针:

template<typename T>
struct const_ptr : std::unique_ptr<T> {
    using std::unique_ptr<T>::unique_ptr;
    const T& operator*() const {
        return std::unique_ptr<T>::operator*();
    }
    const T* operator->() const {
        return std::unique_ptr<T>::operator->();
    }
    T& operator*() {
        return std::unique_ptr<T>::operator*();
    }
    T* operator->() {
        return std::unique_ptr<T>::operator->();
    }
};

然后,试图通过const const_ptr突变对象引用将导致错误:

const_ptr<int> iptr = std::make_unique<int>(6);
*iptr = 7; // okay
const auto ciptr = std::move(iptr);
*ciptr = 2; // error

但是,请注意,由于我们公开扩展std::unique_ptr,因此他的功能仍然可用。您可能需要使用私有继承并使用所有其他功能,除了我们的自定义功能:

template<typename T>
struct const_ptr : private std::unique_ptr<T> {
    using std::unique_ptr<T>::unique_ptr;
    // Implement our operators like above
    using std::unique_ptr<T>::release;
    using std::unique_ptr<T>::reset;
    // .. all other public functions
};