読者です 読者をやめる 読者になる 読者になる

lexical_castで文字列をboolに変換する

C++

How do I use boost::lexical_cast and std::boolalpha? i.e. boost::lexical_cast< bool >(“true”)


boost::lexical_cast()関数は、あらゆる型間の変換を統一的に扱うもので、とても便利です。
しかし、lexical_cast("true");のように、"true"という文字列からbool型に変換しようとしても失敗します。内部的に使用されるstringstreamオブジェクトにboolalphaを設定できればいいのですが、そのようなフォーマット設定は、lexical_castではできないようになっています。


上記StackOverflowで、おもしろい回答が出ていたので紹介します。

#include <iostream>
#include <boost/lexical_cast.hpp>

struct LocaleBool {
    bool data;
    LocaleBool() {}
    LocaleBool(bool data) : data(data) {}
    operator bool() const { return data; }
    friend std::ostream& operator<<(std::ostream& out, LocaleBool b) {
        out << std::boolalpha << b.data;
        return out;
    }
    friend std::istream& operator>>(std::istream& in, LocaleBool& b) {
        in >> std::boolalpha >> b.data;
        return in;
    }
};

int main()
{
    bool b = boost::lexical_cast<LocaleBool>("true");

    std::cout << std::boolalpha << b << std::endl;
}
true

lexical_castで直接bool型に変換するのではなく、boolに変換可能なクラスを用意して、その入出力演算子boolalphaを仕込むのです。
これは非常におもしろい方法だと思います。


このコードだと、LocaleBoolクラス内で設定したboolalphaが、入出力演算子を抜けたあとでも効いたままになってしまうので、Boost.IOStateSaverを使用して関数脱出時に、ストリームのフォーマットを戻すようにしましょう。

#include <iostream>
#include <boost/io/ios_state.hpp>
#include <boost/lexical_cast.hpp>

struct LocaleBool {
    bool data;
    LocaleBool() {}
    LocaleBool(bool data) : data(data) {}
    operator bool() const { return data; }
    friend std::ostream& operator<<(std::ostream& out, LocaleBool b) {
        boost::io::ios_flags_saver ifs(out);
        out << std::boolalpha << b.data;
        return out;
    }
    friend std::istream& operator>>(std::istream& in, LocaleBool& b) {
        boost::io::ios_flags_saver ifs(in);
        in >> std::boolalpha >> b.data;
        return in;
    }
};

int main()
{
    bool b = boost::lexical_cast<LocaleBool>("true");

    std::cout << std::boolalpha << b << std::endl;
}