std::get() の使い道

C++11 で追加された std::get()関数の第一の使い道は何と言っても、std::tuple の要素へのアクセスです。
一方、それ以外のあまり知られていない使い道として、std::array、std::pairに対しても std::get() を使用することもできます。ここでは、std::array、std::pairに対して使用する std::get() について説明します。

std::get() の std::array、std::pair への具体的な使用方法は以下のようになります。
#include <array>
#include <iostream>
#include <utility>

int main(void)
{
    // std::arrayに対してstd::get()を使用
    std::array<int, 3> a{1, 2, 3};
    // a[0]にアクセス
    std::cout << std::get<0>(a); // => "1"

    // std::pairに対してstd::get()を使用
    std::pair<int, int> p{4, 5};
    // p.firstにアクセス
    std::cout << std::get<0>(p); // => "4"

    return 0;
}


std::pair が std::get() に対応しているのは、std::pair は std::tuple の特殊形という関係性(std::pair ∈ std::tuple)を持たすためと考えられます。

std::array に対して std::get() を適用することで、コードの安全性を高めることができます。
std::get() を使って要素にアクセスすると、std::get() のテンプレート引数が範囲外である場合、コンパイルエラーが発生します。
std::array::operator[] では、コンパイル時に範囲外であることが分かっていても、実行時にはそのまま実行されてしまいます。
安全性の観点から見ると、コンパイルエラーが発生する std::get() を使う方が手堅い書き方であると言えるでしょう。

#include <array>
#include <iostream>

int main(void)
{
    std::array<int, 3> a{1, 2, 3};

    // operator[]では、コンパイルエラーにならず、不定動作になる
    std::cout << a[3]; // 不定動作

    // std::get()では、コンパイルエラーになってくれる
    std::cout << std::get<3>(a); // コンパイルエラー!

    return 0;
}


他方、テンプレート引数はコンパイル時定数でなければならないので、以下のような書き方はNGです。あくまで、インデックス値がコンパイル時定数の場合のみ適用可能である点にご留意下さい。
#include <array>
#include <iostream>

int main(void)
{
    std::array<int, 3> a{1, 2, 3};

    for (size_t i = 0; i < a.size(); i++) {
        // テンプレート引数がコンパイル時定数ではないので、コンパイルエラー!
        std::cout << std::get<i>(a) << " ";
    }

    return 0;
}

0 件のコメント:

コメントを投稿