Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the content of a const std::optional always const?

Tags:

c++

c++17

I would assume

std::optional<const std::string>

allows to assign a new value to the optional, but it is not possible to change the string itself and in

const std::optional<const std::string>

it is not possible to do both. But what about the following?

const std::optional<std::string>
like image 480
koalo Avatar asked Mar 08 '19 09:03

koalo


People also ask

Can a const reference refer to a non const object?

No. A reference is simply an alias for an existing object. const is enforced by the compiler; it simply checks that you don't attempt to modify the object through the reference r .

Does Optional make a copy?

When you call the function and pass an instance of T, an optional will be constructed which will own its own copy of T, therefore it will call T's copy constructor. In order to be able to call foo and pass a T without creating a copy, you can declare foo as receiving an optional reference, i.e.

What is std :: optional in C++?

(since C++17) The class template std::optional manages an optional contained value, i.e. a value that may or may not be present. A common use case for optional is the return value of a function that may fail.

What does std :: string& mean?

C++ has in its definition a way to represent a sequence of characters as an object of the class. This class is called std:: string. String class stores the characters as a sequence of bytes with the functionality of allowing access to the single-byte character.


2 Answers

Let's do some testing then:

#include <string>
#include <optional>

int main() {
    using n_c = std::optional<const std::string>;
    using c_n = const std::optional<std::string>;
    using n_n = std::optional<std::string>;

    n_c opt_n_c{"a"};
    c_n opt_c_n{"a"};
    n_n opt_n_n{"a"};

    opt_n_c.emplace("b");
    // opt_c_n.emplace("b");
    opt_n_n.emplace("b");

    // opt_n_c->pop_back();
    // opt_c_n->pop_back();
    opt_n_n->pop_back();
}

The commented out lines do not work.

Think of it like this: A non-const std::optional<T> can have no value or a T, which can be replaced (Not using T::operator=, just destructing the currently held T if it exists and constructing a new one). A non-const std::optional<const T> can do exactly the same, though const T probably doesn't have an operator=, so you can't mutate the held value, but you can still change what value is held. A const std::optional<T> is also "logically const". If a const std::optional<T> equals another const std::optional<T>, and no non-const references are touched, they (should) always remain equal, so the held value (should) not be changed. This is why they return const-references to the held value, and is why const std::optional<T> and const std::optional<const T> are effectively the same.

like image 50
Artyer Avatar answered Nov 15 '22 11:11

Artyer


But what about the following?

const std::optional<std::string>

Everything in the standard library is going to be const-correct - so the accessors on optional are all const-qualified as appropriate. Calling value() or operator*() on a const optional<T> is going to give you a const T& (or const T&&), never a T&.

You have no direct access to a modifiable reference.

Note that if you had a const optional<int*>, on the other hand, it's the pointer itself that is const - not the pointee. So this is fine:

int i = 42;
const std::optional<int*> opt(&i);
*opt.value() = 57;
assert(i == 57);

Is the content of a const std::optional always const?

Now technically, the above doesn't actually answer your question. A const std::optional<std::string> does not hold a const std::string - it holds a std::string that it only exposes const access to. So... technically... but really never do this seriously this is bad... this is well-defined:

const std::optional<std::string> opt("hello"s);
const_cast<std::string&>(opt.value()) = "I am a bad person and I feel bad"s;

Because the string itself was never created as const.

like image 21
Barry Avatar answered Nov 15 '22 12:11

Barry