次のコード:は、STDの動作です::右辺値参照のタプルに危険を取得しますか?
#include <tuple>
int main()
{
auto f = []() -> decltype (auto)
{
return std::get<0> (std::make_tuple (0));
};
return f();
}
(サイレント)未定義の動作を使用してコードを生成 - make_tuple
によって返された一時的な右辺値は、STDを介して伝播される:: <を得る>とdecltype(自動)を介して、戻り値の型の上に。だから、スコープ外になったことを一時的に参照を返してしまいます。ここでそれを参照してくださいhttps://godbolt.org/g/X1UhSw。
さて、あなたはdecltype(auto)
の私の使用は故障していると主張することができます。しかし、(タプルのタイプはstd::tuple<Foo &>
かもしれない)私の汎用コードで私はいつもコピーを作成する必要はありません。私は実際にタプルから正確な値または参照を抽出したいと思います。
私の気持ちはstd::get
のこのオーバーロードは危険であるということである。
template< std::size_t I, class... Types >
constexpr std::tuple_element_t<I, tuple<Types...> >&&
get(tuple<Types...>&& t) noexcept;
タプル要素に左辺値参照を伝播しながら、私はそれは右辺値参照を保持しているとは思わない、おそらく賢明です。
私は、標準化委員会は非常に慎重を介してこれを考えたと確信しているが、これが最良の選択肢と考えた理由を誰も私に説明できますか?我々はstd::tuple{foo{}}
が一時的であることを知って、それはconsume_tuple_first(std::tuple{foo{}})
表現の全期間のために生きるということ、この場合
void consume(foo&&);
template <typename Tuple>
void consume_tuple_first(Tuple&& t)
{
consume(std::get<0>(std::forward<Tuple>(t)));
}
int main()
{
consume_tuple_first(std::tuple{foo{}});
}
:
* "rvalueの参照には当てはまりません" * - あなたが 'forward_as_tuple'を実行するとします。値のカテゴリを保持する必要があります。または、関数の戻り値から1つの値を抽出したい場合。 – StoryTeller
ありがとうございますが、私は本当にそれが価値のカテゴリーを保持しているとは確信していません。たとえば、 'std :: tuple'を返す関数があり、 'std :: get <0>'を呼び出すと、 'int &&'ではなく 'int'を得ることが期待されます。あなたは何か他のものがほしいと思う具体的な例を私に与えることができますか? –
効果的な構造化バインディングには 'get'のオーバーロードが必要ではありませんか? –