Home > front end >  Assigning a non optional variable to std::optional variable
Assigning a non optional variable to std::optional variable

Time:12-22

I have a class with an optional field declared of void const * (I'm also confused if to * outside the angle brackets or inside.

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

In the Test.cpp file.

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

enter image description here

CodePudding user response:

In your example, where _data is a non-const pointer to a std::optional (it doesn't matter that the std::optional holds a const void type), you're trying to assign a pointer to a const object (of unknown void type) to a non-const pointer.

This violates the contract of your class constructor, where you promise not to modify the object being pointed at (not just in the constructor, but ever). Consider this simplified example:

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
    }
}

Your issue has nothing to do with std::optional.

Consider that you might not even need to wrap your pointer in a std::optional, since pointers already have the natural nullable-concept of 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.
        }
    }
}

On the concept of std::optional, pointers, and nullable

it's the responsibility of the caller of the function to check for the null for the returned value

correct - and your user would have to do with a std::optional anyway.

Another option is to specify that it's "undefined behavior" or "illegal" for a user of your class to construct it with a nullptr. And that it's not a valid state for the object to exist with a nullptr. That shifts the responsibility on the "creator" of the object, and not the "user" (even though they're likely the same human). This all depends on whether it's valid for your _data to be nullptr.

Decide what the valid states of your object are allowed to be, and whose responsibility it is to enforce that. If you design your interface correctly, you can eliminate a lot of if checks that would otherwise need to be scattered throughout all layers of the code.

Some of the responsibility lives with the object creator (user), some of the responsibility lives within the class (this could be shared with the user-creator for validity checks, or ignored), and some lies with the object user (application developer).

  • Related