1. ホーム
  2. c++

[解決済み] initializer_list と移動のセマンティクス

2022-10-28 10:30:12

質問

の外に要素を移動することはできますか? std::initializer_list<T> ?

#include <initializer_list>
#include <utility>

template<typename T>
void foo(std::initializer_list<T> list)
{
    for (auto it = list.begin(); it != list.end(); ++it)
    {
        bar(std::move(*it));   // kosher?
    }
}

以降 std::intializer_list<T> はコンパイラの特別な注意を必要とし、C++ 標準ライブラリの通常のコンテナのような値セマンティクスを持たないので、むしろ安全策をとって尋ねることにします。

どのように解決するのですか?

いいえ、それは意図したとおりには動作しません。私は、次のように考えていたので、これにはかなり驚いています。 initializer_list が存在し、テンポラリの配列を、それらが move 'd.

beginend に対して initializer_list 戻る const T * の結果は move の結果は T const && - であり、不変のrvalue参照です。このような式は意味のある移動ができません。これは関数パラメータにバインドされ T const & 型の関数パラメータにバインドされ、rvalueはconst lvalue参照にバインドされるため、コピーセマンティクスが表示されます。

おそらくこの理由は、コンパイラが initializer_list を静的に初期化された定数とすることをコンパイラが選択できるようにするためだと思われますが、その型を initializer_list または const initializer_list を期待するのか、それともコンパイラの裁量に任せるのか、 ユーザはわかりません。 const の結果を期待するのか、それともミュータブルな結果を期待するのか、 ユーザにはわかりません。 beginend . しかし、これは私の直感に過ぎず、おそらく私が間違っている正当な理由があるのでしょう。

更新しました。 私が書いたのは ISO 提案 のために initializer_list のサポートに関する ISO 提案です。まだ最初の草案であり、どこにも実装されていませんが、問題のより詳しい分析のために見ることができます。