2017-05-03 4 views
61

私はstd::tieをよく使っています。std :: tieはどのように機能しますか?

auto test() 
{ 
    int a, b; 
    std::tie(a, b) = std::make_tuple(2, 3); 
    // a is now 2, b is now 3 
    return a + b; // 5 
} 

しかし、どのようにこの黒魔術仕事がない:それはので、私はちょうどそれを受け入れてきた作品? std::tieによって作成された一時的な変更はどのようにしてabに変更されますか?言語機能ではなくライブラリ機能なので、もっと面白いと思うので、確かに実装して理解できるものです。

答えて

94

コアの概念を明確にするために、より基本的な例にしましょう。我々は前進するために知っておく必要があり

int a; 
std::tie(a) = std::make_tuple(24); 
return a; // 24 

物事:

  • std::tieは、複数の値を(タプル)を返す関数のために有用であるが、我々はただ一つの値を持つだけで罰金、それを理解することができますstd::tieは、参照のタプルを構成して返します。
  • std::tuple<int>およびstd::tuple<int&>は、2つの全く異なるクラスであり、それらの間は接続されておらず、同じテンプレートから生成されたものではありません。std::tuple

    template< class... UTypes > 
    tuple& operator=(const tuple<UTypes...>& other); 
    

    (3)全てのiについて、割り当てstd::get<i>(other)std::get<i>(*this)た:

  • タプルoperator=は各メンバーがcppreference個別-から割り当てられ、異なる種類(同じ数)のタプルを受け付ける有します。

次のステップは、あなたの方法で取得し、それらの機能を取り除くことですので、我々はこれに我々のコードを変換することができます。

int a; 
std::tuple<int&>{a} = std::tuple<int>{24}; 
return a; // 24 

次のステップは、正確に何を参照することですそれらの構造の中で起こる。このため 、私たちの事業のために最低限まで剥奪std::tuple<int>Tr置換基std::tuple<int&>のための2種類のT置換基、作成:

struct T { // substituent for std::tuple<int> 
    int x; 
}; 

struct Tr { // substituent for std::tuple<int&> 
    int& xr; 

    auto operator=(const T& other) 
    { 
     // std::get<I>(*this) = std::get<I>(other); 
     xr = other.x; 
    } 
}; 

auto foo() 
{ 
    int a; 
    Tr{a} = T{24}; 

    return a; // 24 
} 

をそして最後に、私は、ウェル(すべて一緒構造を取り除くのが好きそれは100%同じではないのですが、それは)私たちのために十分に近い、それを可能にするのに十分明示ます:

auto foo() 
{ 
    int a; 

    { // block substituent for temporary variables 

    // Tr{a} 
    int& tr_xr = a; 

    // T{24} 
    int t_x = 24; 

    // = (asignement) 
    tr_xr = t_x; 
    } 

    return a; // 24 
} 

だから、基本的に、std::tie(a)aへのデータメンバの参照を初期化します。 std::tuple<int>(24)は値24のデータメンバーを作成し、割り当ては最初の構造のデータメンバー参照に24を割り当てます。しかし、そのデータメンバーはaにバインドされた参照であるため、基本的には24aに割り当てます。

13

これは決してあなたの質問に答えるものではありませんが、C++ 17は基本的に(コンパイラのサポートを受けて)準備ができているため、投稿してもらうようにしています。 C++の現在のバージョンと将来のバージョンも動作します。

C++では、ストラクチャードバインディングと呼ばれるものを好むほどstd::tieを傷つけることができます。それらは同じことを行います(は同じではありませんが、同じ効果があります)。ただし、少数の文字を入力する必要がありますが、ライブラリのサポートは必要ありません。も参照を取得できます。それはあなたが望むものになります。

(C++ 17件のコンストラクタでのことに注意してくださいは、引数控除は、そう make_tupleも、多少余分になっています。)

int a, b; 
std::tie(a, b) = std::make_tuple(2, 3); 

// C++17 
auto [c, d] = std::make_tuple(4, 5); 
auto [e, f] = std::tuple(6, 7); 
std::tuple t(8,9); auto& [g, h] = t; // not possible with std::tie 
+2

その最後の行は、私は少し心配ですコンパイルした場合。それは違法な一時的なものへの参照をバインドするように見えます。 –

+0

@NirFriedmanこの場合、生涯延長はありませんか? – Neil

+2

@ニールルこれは、値の参照または定数の左辺の参照のいずれかである必要があります。左辺値の参照を仮値にバインドすることはできません(一時的)。これは、年齢のMSVCの "拡張"されていますが。 –

関連する問題