C++と色々

主にC++やプログラムに関する記事を投稿します。

boost::any

boost::anyは動的型とも言われています。まるで動的型付け言語のようにboost::anyにはあらゆる型のオブジェクトを代入し、取り出すことができます。boost::anyに格納することが出来る型の要件は以下の3つです。

  • コピーコンストラクト可能なこと
  • 例外に対して強い保証をもった代入演算子があること
  • デストラクタが例外を投げない保証をしていること

以上の3点を満たした型ならboost::anyに格納することができます。といっても普通はどんなクラスを作ってもデストラクタは例外を投げないにするのは当たり前ですし、代入可能なクラスなら例外を投げないswapを用いてコピーと交換法で代入演算子を例外に対して強い保証をする定義をするのはよくあることなので、実質ほぼすべての型で使えます。格納したオブジェクトはany_castを使って取り出すことができます。キャストに失敗した時はbad_any_cast例外が投げられます。

以下サンプルです。

#include <iostream>
#include <string>
#include <vector>
#include <boost/any.hpp>

int main()
{
    std::vector<boost::any> vec;

    vec.push_back(3);
    vec.push_back(3.14f);
    vec.push_back(3.14159);
    vec.push_back(std::string("3.14"));

    for(const auto& it : vec)
    {
        if(it.type() == typeid(int))
        {
            std::cout << "int " << boost::any_cast<int>(it) << std::endl;
        }
        else if(it.type() == typeid(float))
        {
            std::cout << "float " << boost::any_cast<float>(it) << std::endl;
        }
        else if(it.type() == typeid(double))
        {
            std::cout << "double " << boost::any_cast<double>(it) << std::endl;
        }
        else if(it.type() == typeid(std::string))
        {
            std::cout << "std::string " << boost::any_cast<std::string>(it) << std::endl;
        }
    }
}

実行結果

int 3
float 3.14
double 3.14159
std::string 3.14
続行するには何かキーを押してください . . .

このように、あらゆる型を格納することができるコンテナをヘテロなコンテナと言うそうです。