Подтвердить что ты не робот

Является ли адрес std :: optional стабильным?

Скажем, у меня есть std::optional<T>. Я сбрасываю и присваиваю значение несколько раз. Является ли адрес значения (когда присутствует) всегда одинаковым для данного необязательного?

Другими словами:

#include <cassert>
#include <optional>
#include <string>

template<typename T>
auto test()
{
    auto opt = std::optional<T>{T{}};
    auto* ptr = &*opt;

    opt.reset();
    opt = T{};

    assert(ptr == &*opt); // Can this assert fail?
}

int main()
{
    test<int>();
    test<double>();
    test<std::string>();
    // ...
}

Является ли стандарт гарантией стабильности адреса значения?

4b9b3361

Ответ 1

Является ли стандарт гарантией стабильности адреса значения?

С моей точки зрения, неуказано, стабилен ли адрес или нет.

Формально стандарт только гарантирует отсутствие динамических распределений для объекта, содержащегося в std::optional и содержащий объект хранится как часть std::optional:

23.6.3. Шаблон класса необязательный [optional.optional]

Любой экземпляр необязательного в любой момент времени либо содержит значение, либо не содержит значения. Когда экземпляр необязательного значения содержит значение, это означает, что объект типа T, называемый необязательным объектом, содержащим значение, выделяется в хранилище необязательного объекта. Реализациям не разрешено использовать дополнительное хранилище, такое как динамическая память, для распределения его содержащегося значения. Содержащееся значение должно быть выделено в области дополнительного хранилища, подходящим образом выровненного для типа T. Когда объект типа необязательный преобразуется контекстом в bool, преобразование возвращает true, если объект содержит значение; в противном случае преобразование возвращает false.

Фактический механизм хранения определяется конкретной реализацией, поэтому потенциальный адрес может измениться.

На практике, однако, реализация будет использовать что - то вроде aligned_storage (см увеличить реализацию) или union (как GCC делает) и сохранить адрес объекта, содержащего то же самое.