С++ 17 make_Optional constexpr-ness

На этой странице говорится, что функция make_optional в C++17 возвращает constexpr optional<...>. Я думаю (хотя могу ошибаться), для этого потребуется, чтобы optional<T> имел constexpr конструктор копирования или перемещения. Однако на этой странице также говорится, что это не так.

Я не знаю, как можно реализовать make_optional, поскольку в настоящее время существует черновик C++1z. См. этот пост для уточнения. Есть ли какое-то обходное решение, или, может быть, это просто ошибка стандартного черновика/cppreference?


person Zizheng Tai    schedule 21.06.2016    source источник
comment
В этом вопросе нет вопроса.   -  person user253751    schedule 21.06.2016
comment
@immibis Обновлено :)   -  person Zizheng Tai    schedule 21.06.2016
comment
cppreference не придумал это constexpr из воздуха, знаете ли...   -  person T.C.    schedule 21.06.2016
comment
@Т.С. Да… но кто-то где-то ошибся…   -  person Zizheng Tai    schedule 21.06.2016
comment
@Т.С. Оказалось, я здесь допустил ошибку.   -  person Zizheng Tai    schedule 21.06.2016


Ответы (2)


Спасибо @Yakk и @T.C. за их пояснения. Я чувствую, что пример должен прояснить ситуацию:

struct wrapper {
    int value;

    // non-explicit constexpr constructor
    constexpr wrapper(int v) noexcept : value(v) {}

    // non-constexpr copy & move constructors
    wrapper(const wrapper& that) noexcept : value(that.value) {}
    wrapper(wrapper&& that) noexcept : value(that.value) {}
};

constexpr wrapper make_wrapper(int v)
{
    return {v};
}

int main()
{
    constexpr auto x = make_wrapper(123);  // error! copy/move construction,
                                           // but no constexpr copy/move ctor

    constexpr int y = make_wrapper(123).value;  // ok
    static_assert(y == 123, "");                // passed
}

Итак, make_wrapper успешно возвращает constexpr wrapper; это конструкция копирования/перемещения (хотя обычно игнорируемая компиляторами), которая предотвращает компиляцию кода, поскольку конструктора constexpr копирования/перемещения нет.

Мы можем проверить constexpr-ность возвращенного (временного) wrapper объекта, используя значение его члена для инициализации переменной constexpr.

person Zizheng Tai    schedule 21.06.2016

Вы можете напрямую создавать возвращаемые значения в С++ 11 с помощью return {something};. Если есть какие-либо неявные ctor, которые являются constexpr, вы можете вернуть их из функции.

person Yakk - Adam Nevraumont    schedule 21.06.2016
comment
Я считаю, что это иллюзия, вызванная копированием. Без копирования-исключения он не скомпилируется: gcc, clang. - person Zizheng Tai; 21.06.2016
comment
И, как упоминалось в ответах в моем связанном сообщении, даже если компилятор выполняет копирование-исключение, конструктор копирования/перемещения constexpr должен быть доступен (даже если он в конечном итоге не используется). - person Zizheng Tai; 21.06.2016
comment
@ZizhengTai Это ваш собственный пример виноват в том, что он делает еще одну копию. godbolt.org/g/jT7mHd Инициализация списка копирования не создает временных, концептуальных или иных. - person T.C.; 21.06.2016
comment
@Т.С. Если я не использую объект-оболочку, какой смысл его делать? Говорят, что std::make_optional возвращает constexpr std::optional, в моих (и ваших) примерах make_wrapper не может возвращать constexpr Wrapper. - person Zizheng Tai; 21.06.2016
comment
@ZizhengTai В какой вселенной он возвращает constexpr std::optional? Он возвращает std::optional. Это шаблон функции constexpr. - person T.C.; 21.06.2016
comment
@Т.С. Может быть, я ошибаюсь, но определенно я запутался... не означает ли это, что если аргумент, переданный make_optional, является константой времени компиляции, то возвращаемый optional также будет единицей? - person Zizheng Tai; 21.06.2016
comment
С другой стороны, мне интересно, почему они не представили std::optional::iterator и const_iterator. - person bipll; 21.06.2016
comment
@Т.С. Это ваш собственный пример виноват в том, что он делает еще одну копию. А, я понимаю, что вы имеете в виду. Проблема не в return, а в =. - person Zizheng Tai; 21.06.2016