【问题标题】:Assigning a non optional variable to std::optional variable将非可选变量分配给 std::optional 变量
【发布时间】:2022-01-23 07:46:23
【问题描述】:

我有一个带有声明为void const * 的可选字段的类(我也很困惑是在尖括号之外还是在里面。

class Test {
protected:
    std::optional<void const> *_data;  // void const *_data
public:
    explict Test(void const *data = nullptr);
}

在 Test.cpp 文件中。

Test(const void *data) {
    this->_data = data; // error
}

【问题讨论】:

  • 请详细说明您的具体错误。
  • void const* 也等价于const void*。类型说明符中的 const 指的是 const 左侧的“事物”,除非在特殊情况下,您的类型中的“第一个”事物应该是 const,并且您可以将 const 放置在任一它的左边或右边。我认为这只是为了可读性 - 也许是向后兼容。其他人可以谈谈历史原因。我个人更喜欢const void*void const*,但你可以在野外找到两者。这只是一种风格。
  • 既然您已经通过void const*const void* 的比较清楚了,我也更喜欢const,因为这是我在其他语言中已经习惯的。谢谢。
  • 函数调用者有责任检查返回值是否为 null 正确 - 无论如何,您的用户都必须使用 std::optional。现在,另一种选择是指定类的用户使用nullptr 构造它是“未定义行为”或“非法”。并且对象内部存在nullptr 不是有效状态。这将责任归于对象的“创建者”,而不是“用户”(即使他们可能是同一个人)。这一切都取决于您的 _data 是否为 nullptr
  • constexpr static char const *const NAME = "Test"; 是一个const 指针(指针 的值不得更改)到const charchars 的值在数组不得更改)。 constexpr 使其中的一些冗余,因为 constexpr 暗示 const 反正。

标签: c++ optional


【解决方案1】:

在您的示例中,_data 是指向 std::optional 的非常量指针(std::optional 持有 const void 类型并不重要),您正试图将指针分配给一个const 对象(未知的void 类型)指向一个非常量指针。

这违反了你的类构造函数的约定,你承诺不修改指向的对象(不仅仅是在构造函数中,而是永远)。考虑这个简化的例子:

template <typename T>
Test {
protected:
    T* _data;

public:
    explict Test(const void * data = nullptr) {
        _data = data; // ERROR: can't assign a const-pointer to a non-const pointer
    }
}

您的问题与std::optional无关。

考虑一下,您甚至可能不需要将指针包装在 std::optional 中,因为指针已经具有 nullptr 的自然可空概念:

class Test {
protected:
    const void* _data;
public:
    explict Test(void const *data = nullptr) {
        _data = data;
    }

    void do_thing() const {
        if (_data) { // nullable semantics naturally work on pointers, no need for `std::optional`
        // UNLESS `nullptr` isn't "null enough" for your application
            // do (const-qualified) operation on _data.
        }
    }
}

关于std::optional、指针和可空的概念

函数调用者有责任检查返回值是否为空

正确 - 无论如何,您的用户都必须使用 std::optional

另一个选项是指定它是“未定义的行为”或“非法”,让您的类的用户使用nullptr 构造它。并且以nullptr 存在的对象不是有效状态。这将责任转移给对象的“创建者”,而不是“用户”(即使他们可能是同一个人)。这完全取决于您的_data 是否有效为nullptr

决定允许您的对象的有效状态是什么,以及由谁负责执行该状态。如果你正确设计了你的界面,你可以消除很多if检查,否则这些检查需要分散在代码的所有层中。

一些责任属于对象创建者(用户),一些责任属于类(这可以与用户创建者共享以进行有效性检查,或忽略),还有一些属于对象用户(应用程序开发人员)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多