1. ホーム
  2. c++

[解決済み] std::tieはどのように機能するのですか?

2022-03-02 20:31:03

質問

私は 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 ? 言語の機能ではなくライブラリの機能なので、きっと自分たちで実装して理解できるものだと思うので、こちらの方が興味深いです。

解決方法は?

核となる考え方を明確にするために、より基本的な例に落とし込んで考えてみましょう。とはいえ std::tie は、より多くの値を(タプルで)返す関数に便利ですが、1つの値で十分理解できます。

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

前に進むために必要なこと。

  • std::tie は、参照のタプルを構築して返します。
  • std::tuple<int>std::tuple<int&> は2つの全く異なるクラスで、同じテンプレートから生成されたということ以外、両者の間には何の関連性もありません。 std::tuple .
  • タプルには operator= 異なる型(ただし同じ番号)のタプルを受け入れ、各メンバーは個別に割り当てられる。 参照 :

    <ブロッククオート
    template< class... UTypes >
    tuple& operator=( const tuple<UTypes...>& other );
    
    

    (3) すべてのiについて std::get<i>(other)std::get<i>(*this) .

次は、邪魔にしかならない関数を取り除くことで、このようなコードに変換することができます。

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

次のステップは、これらの構造体の内部で何が起こっているかを正確に確認することです。 このために、私は2つのタイプを作成します。 T の代用品です。 std::tuple<int>Tr 置換基 std::tuple<int&> を、操作のために必要最低限まで削ぎ落としたものです。

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 .