Seasons.NET

ちょっとした技術ブログです

boost::tokenizerを使うときの注意。

以下のクラスを作って、文字列のパースした状態を保存しておきたいと思った際に、
うっかりtokenizerに渡す文字列は、shared_ptr管理かメンバ変数で持たせるかの
いずれかにしておかないと大変な事になります。

というのも

    tok = boost::shared_ptr< CsvTok >( new CsvTok( data_ , *sep ) );

ここで渡されたdata_(文字列)情報は、コピーされず、begin(),end()で取得されてしまうので、
関数を抜けると不定になるのです。

class CsvParser
{
public:
    typedef boost::char_separator< char > CsvSep;
    typedef boost::tokenizer< CsvSep > CsvTok;

private:
    boost::shared_ptr< CsvTok > tok;
    boost::shared_ptr< CsvSep > sep;
    std::string data_;

public:
    CsvParser();

    bool Split( __in std::string str );

    const CsvParser::CsvTok& Tokens( void ) const
    {
        return *tok;
    }
};
CsvParser::CsvParser()
{
}

bool CsvParser::Split( __in std::string str )
{
    sep = boost::shared_ptr< CsvSep >( new CsvSep(",") );
    data_ = str;

    // トークンを分割する
    tok = boost::shared_ptr< CsvTok >( new CsvTok( data_ , *sep ) );
    ASSERT( tok.get()!=NULL );

    return true;
}