次のメソッドを呼び出す必要があると想像してください。
std::Tuple<int, int, int> foo();
C++ 17では、関数を呼び出して、タプルを1行でアンパックできます。
auto [a, b, c] = foo();
さて、どうすればb
とc
のみを保存し、a
を破棄できますか?
現在、私は2つのオプションしか認識していません。
1-自動展開時にダミー変数を使用できます
ただし、ダミー変数は使用されず、警告が発行されるため、警告を表示したくない場合、コードを見るのは非常に不快です。
#pragma warning(Push)
#pragma warning(disable:4101)
// ReSharper disable once CppDeclaratorNeverUsed
auto [_, b, c] = foo();
#pragma warning(pop)
2-タプル全体を保存し、std::get
を使用して、必要な変数のみへの参照を取得できます。コードはそれほど不快ではありませんが、構文はそれほど単純ではありません。
さらに、このコードのサイズは、タプルに保持する新しい値ごとに1行ずつ増加します。
auto Tuple = foo();
int b = std::get<1>(Tuple);
int c = std::get<2>(Tuple);
タプルの一部のパラメータのみをアンパックする別のより簡単な方法はありますか?
別の方法は、std::tie
を使用することです:
int b, c;
std::tie(std::ignore, b, c) = foo();
編集
コメントで述べたように、このアプローチにはいくつかの問題があります。
残念ながら structured bindings はメンバーの破棄を明示的にサポートしておらず、 [[maybe_unused]]
などの属性は構造化バインディング(その提案があります: P0609: "構造化バインディングの属性" ) 。
考えられる解決策は次のとおりです。
auto [a, b, c] = foo();
(void) a; // unused
std::Tuple
の特定のインデックスのみを返すヘルパー関数を作成できます。
template <size_t... Is, typename Tuple>
auto take_only(Tuple&& Tuple) {
using T = std::remove_reference_t<Tuple>;
return std::Tuple<std::Tuple_element_t<Is, T>...>(
std::get<Is>(std::forward<Tuple>(Tuple))...);
}
auto [b, c] = take_only<1, 2>(foo());
または、頭か何かを落とします:
template <size_t... Is, typename Tuple>
auto drop_head_impl(Tuple&& Tuple, std::index_sequence<0, Is...> ) {
return take_only<Is...>(std::forward<Tuple>(Tuple));
}
template <typename Tuple>
auto drop_head(Tuple&& Tuple) {
return drop_head_impl(std::forward<Tuple>(Tuple),
std::make_index_sequence<std::Tuple_size_v<std::decay_t<Tuple>>>());
}
auto [b, c] = drop_head(foo());
しかし、上記の実装には、構造化バインディングを直接使用することで発生しない寿命の複雑さの問題がほぼ確実にあります。ここには寿命の拡張機能がないためです。
それで、ちょうど Vittorioが言う :
auto [a, b, c] = foo();
(void)a;
VS 15.7プレビューでは、MSVCにはすでに fixed thisがあります。最終的な15.7リリースは、今後数週間で利用可能になります。つまり、すべての主要なコンパイラの最新リリースでサポートされている現在のロジックは次のとおりです。
構造化バインディング宣言内のバインディングのいずれも使用されていない場合、[[maybe_unused]]
属性を使用して、警告を黙らせることができます。
[[maybe_unused]] auto [a、b、c] = foo();