2016-06-21 21 views
7

This pageは、C++ 17のmake_optional関数がconstexpr optional<...>を返します。私は思うが(私は間違っているかもしれない)これはoptional<T>にはconstexprコピーまたは移動コンストラクタが必要であると思うだろう。しかし、this pageもそうではないと言います。C++ 17 make_optional constexpr-ness

make_optionalは、現在C++ 1zドラフトが実装されているため、どのように実装できますかわかりません。説明のためにthis postを参照してください。いくつかの回避策がありますか、それとも単に標準のドラフト/ cppreferenceの間違いですか?

+0

この質問に疑問はありません。 – immibis

+0

@immibis更新された:) –

+1

cppreferenceは、その「constexpr」を薄い空気から取り戻しませんでした。あなたは知っています... –

答えて

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コピー/移動コンストラクタがないので、コードがコンパイルされないようにするのは、コピー/移動のコンストラクションです(通常はコンパイラによって省略されます)。

返された(一時的な)wrapperオブジェクトのメンバ値を使用してconstexpr変数を初期化することによって、constexprの状態を確認できます。

1

return {something};を使用してC++ 11で戻り値を直接構築することができます。constexprの非明示的なctorsがある場合は、それを関数から返すことができます。

+0

私はこれがコピー・エリシジョンによる錯覚だと信じています。コピー・エリジョンがなければコンパイルされません:[gcc](https://godbolt.org/g/X3pTzv)、[clang](https://godbolt.org/g/AiqxxV) –

+0

私のリンクされたポストの答えとして、コンパイラがコピーエリジョンを実行したとしても、 'constexpr'コピー/移動コンストラクタは(最終的には使用されなくても)アクセス可能でなければなりません。 –

+0

@ ZizhengTaiそれは別のコピーを作っているというあなた自身の例のせいです。 https://godbolt.org/g/jT7mHdコピーリストの初期化では、概念的なものとそうでないものとの両方の一時的なものは作成されません。 –

関連する問題