C++17味見:構造化バインド宣言(Structured Binding Declaration)

8409 ワード

構造化バインド宣言
構造化バインド宣言とは、1回の宣言に複数の変数を同時に導入し、初期化式の各サブオブジェクトをバインドする構文形式です.構造化バインド宣言はautoを使用して複数の変数を宣言し、すべての変数をカッコで囲む必要があります.
cv-auto+   [  1,   2, ...   n ] =       ;
cv-auto+   [  1,   2, ...   n ] (      );
cv-auto+   [  1,   2, ...   n ] {      };
//    cv-auto+      auto, auto const, auto &, auto&&     

構造化バインディングで宣言される変数には、2つの形式があります.1.非参照変数です.初期化式オブジェクトをコピーする必要があります.変数は、初期化式オブジェクトがコピーしたサブオブジェクトをバインドします.2.変数を参照します.この場合、初期化式オブジェクトはコピーする必要はありません.変数は、初期化式オブジェクト自体のサブオブジェクトにバインドされます.
構造化バインディングの初期化式には、3つのタイプがあります.1.配列タイプ.変数がバインドされているのは配列の各要素です.2.pair tupleなどはtuple_sizeのタイプをサポートし、このとき変数がバインドされているのはget<0>(e),get<1>(e),get<2>(e)…ここでEはタイプを指し、eはオブジェクトを指す.3.publicメンバーを持つ構造タイプ.変数は、構造オブジェクトの各publicメンバーにバインドされます.
C++17コード
#include 
#include 
#include 
#include 

using namespace std;

struct S {
    int a, b;
};

map<string, int> get_map()
{
    return {
        { "hello", 1 },
        { "world", 2 },
        { "it's",  3 },
        { "me",    4 },
    };
}

int main()
{
    auto [a, b] = pair(2, "3"s);
    cout << a << b << endl; // 23

    set<string> myset;
    if (auto [iter, success] = myset.insert("Hello"); success) 
       cout << *iter << endl; // Hello

    int arr[] = {1, 2};
    const auto& [m, n] = arr;
    cout << m << n << endl; //12

    S s = {4, 5};
    auto& [x, y] = s;
    x = 0, y = 1;
    cout << s.a << s.b << endl; // 01

    for (auto&& [k, v] : get_map())
        cout << "k=" << k << " v=" << v << endl;
    // k=hello v=1
    // k=it's v=3
    // k=me v=4
    // k=world v=2
}

コードの説明
  • コードの25行目は、intタイプのaとstringタイプのbを構造化バインディングで宣言し、初期化式のpairオブジェクトのfirstとsecondをそれぞれバインディングした.
  • コード29行目は、構造化バインドを使用して反復タイプのiterとboolタイプのsuccessを宣言し、初期化式のpairオブジェクトのfirstとsecondをそれぞれバインドします.
  • コード33行目は構造化バインドを用いてconst int&タイプのmとnを宣言し、初期化式のarr配列の2つの要素をそれぞれバインドした.
  • コード37行目は、初期化式のsオブジェクトの2つのデータメンバーaおよびbをそれぞれバインドする構造化バインドを用いてint&タイプのxおよびyを宣言する.
  • コード41行目はstring&&タイプのkとintタイプのvを構造化バインドで宣言し、初期化式のpairオブジェクトのfirstとsecondをそれぞれバインドした.

  • C++14等価コード
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    struct S {
        int a, b;
    };
    
    map<string, int> get_map()
    {
        return {
            { "hello", 1 },
            { "world", 2 },
            { "it's",  3 },
            { "me",    4 },
        };
    }
    
    int main()
    {
        auto kv = make_pair(2, "3"s);
        auto& a = kv.first; auto& b = kv.second;
    
        set<string> myset;
        set<string>::iterator iter;
        bool success;
        tie(iter, success) = myset.insert("Hello");
        if (success) 
           cout << *iter << endl; // Hello
    
        int arr[] = {1, 2};
        const auto &m = arr[0], &n = arr[1];
        cout << m << n << endl; //12
    
        S s = {4, 5};
        auto &x = s.a, &y = s.b;
        x = 0, y = 1;
        cout << s.a << s.b << endl; // 01
    
        for (auto&& kv : get_map()) {
            auto&& k = forward<decltype(kv.first)>(kv.first);
            auto&& v = forward<decltype(kv.second)>(kv.second);
            cout << "k=" << k << " v=" << v << endl;
        }
        // k=hello v=1
        // k=it's v=3
        // k=me v=4
        // k=world v=2
    }