Содержимое const std :: необязательно всегда const? - PullRequest
1 голос
/ 08 марта 2019

Я бы предположил, что

std::optional<const std::string>

позволяет назначить новое значение для необязательного, но невозможно изменить саму строку, а в

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

это невозможносделать оба.Но как насчет следующего?

const std::optional<std::string>

Ответы [ 2 ]

1 голос
/ 08 марта 2019

А как насчет следующего?

const std::optional<std::string>

Все в стандартной библиотеке будет const -корректным - поэтому все методы доступа на optional все const - квалифицируется как соответствующий.Вызов value() или operator*() на const optional<T> даст вам const T& (или const T&&), а не T&.

У вас нет прямого доступа к изменяемой ссылке.

Обратите внимание, что если у вас есть const optional<int*>, то, с другой стороны, сам указатель является const, а не указателем.Так что это нормально:

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

Является ли содержимое const std::optional всегда const?

Технически, вышеприведенное фактически не отвечает на ваш вопрос.const std::optional<std::string> не содержит const std::string - он содержит std::string, к которому он предоставляет только const доступ.Итак ... технически ... но на самом деле никогда не делайте этого всерьез, это плохо ... это хорошо определено:

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

Поскольку сам string никогда не создавался как const.

1 голос
/ 08 марта 2019

Давайте проведем некоторое тестирование:

#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();
}

Комментированные строки не работают.

Думайте об этом так: неконстантный std::optional<T> может не иметь значения или T, который может быть заменен (не используется T::operator=, просто уничтожается текущий T, если он существует, и создается новенький). Неконстантный std::optional<const T> может делать то же самое, хотя const T, вероятно, не имеет operator=, поэтому вы не можете изменить значение удержания, но вы все равно можете изменить, какое значение удерживается. A const std::optional<T> также «логически постоянен». Если a const std::optional<T> равно другому const std::optional<T>, и не затрагиваются неконстантные ссылки, они (должны) всегда остаются равными, поэтому удерживаемое значение (не) не должно изменяться. Вот почему они возвращают const-ссылки на удерживаемое значение, и именно поэтому const std::optional<T> и const std::optional<const T> фактически одинаковы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...