C++17中的make_optional的constexpr特性

7

这个页面显示,C++17中的make_optional函数返回一个constexpr optional<...>。我认为(虽然可能不正确),这将需要optional<T>具有constexpr复制或移动构造函数。但是,这个页面也说这不是情况。

我不知道如何实现make_optional,因为C++1z草案目前的状态。请参考此帖子以了解更多信息。是否有一些解决方法,或者只是标准草案和cppreference的错误?


这个问题中并没有问题。 - user253751
@immibis 已更新 :) - Zizheng Tai
1
cppreference并不是凭空想出了constexpr,你知道的... - T.C.
@T.C. 是的,我有...但肯定是某个地方出了错... - Zizheng Tai
@T.C. 结果是 在这里犯了一个错误。 - Zizheng Tai
2个回答

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性。


1
你可以直接使用 C++11 来构造返回值,如 return {something};。如果有任何非显式的构造函数是 constexpr,则可以从函数中返回它。

我认为这是由于复制省略引起的幻觉。如果没有复制省略,它将无法编译:gccclang - Zizheng Tai
@ZizhengTai 这是你自己的示例的问题,它正在创建另一个副本。https://godbolt.org/g/jT7mHd 复制列表初始化不会创建临时对象,无论是概念上还是其他方面。 - T.C.
@T.C. 如果我不使用包装对象,那么制作它有什么意义呢?据说std::make_optional返回一个constexpr std::optional,在我的(和你的)示例中,make_wrapper 无法返回一个constexpr Wrapper - Zizheng Tai
2
@ZizhengTai 在哪个宇宙中它会返回 constexpr std::optional?它返回的是 std::optional。它是一个 constexpr 函数模板。 - T.C.
1
@T.C. 这是你自己的例子的问题,它正在创建另一个副本。 哦,我明白你的意思了。问题不在于 return,而在于 = - Zizheng Tai
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接