この以前の投稿を拡張して、私std::vector<boost::variant<double,std::string>>
は単にではなくキャプチャしようと思いましたboost::variant<double,std::string>
が、最初に同じ古い入力から始めます。
入力'foo'と42.7が与えられた場合の出力は次のとおりです。
/tmp$ g++ -g -std=c++11 sandbox.cpp -o sandbox && ./sandbox
<m_rule>
<try>foo</try>
<success></success>
<attributes>[[f, o, o]]</attributes>
</m_rule>
<m_rule>
<try>42.7</try>
<success></success>
<attributes>[42.7]</attributes>
</m_rule>
std::string='foo'
double='42.7'
/tmp$ g++ -g -std=c++11 -DDO_VECTOR sandbox.cpp -o sandbox && ./sandbox
<m_rule>
<try>foo</try>
<success></success>
<attributes>[[102, 111, 111]]</attributes>
</m_rule>
<m_rule>
<try>42.7</try>
<success></success>
<attributes>[[42.7]]</attributes>
</m_rule>
double='111'
double='42.7'
/tmp$
私が理解していない何らかの理由で、パーサーは「foo」のASCII値を生成していて、混乱を引き起こしているようです。
DO_VECTORをオンにするときにパーサーを変更する必要がありますか?
別のコンテナを使用する必要がありますか?
コード
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/variant.hpp>
// #define DO_VECTOR
namespace {
namespace qi = boost::spirit::qi;
typedef std::string::const_iterator Iterator;
#ifdef DO_VECTOR
typedef std::vector<boost::variant<double, std::string>> MY_TYPE;
#else
typedef boost::variant<double, std::string> MY_TYPE;
#endif
class my_visitor
: public boost::static_visitor<>
{
public:
my_visitor( std::string& result ) : m_str( result ) { }
void operator()( double& operand )
{
std::ostringstream oss;
oss << "double='" << operand << "'";
m_str = oss.str();
}
void operator()( std::string& operand )
{
m_str = "std::string='";
m_str.append( operand );
m_str.append( "'" );
}
std::string& m_str;
};
// -----------------------------------------------------------------------------
struct variant_grammar :
qi::grammar<Iterator, MY_TYPE()>
{
qi::rule<Iterator, MY_TYPE()> m_rule;
variant_grammar() : variant_grammar::base_type(m_rule)
{
m_rule %= (qi::double_ | +qi::char_);
BOOST_SPIRIT_DEBUG_NODE( m_rule );
}
};
}
// -----------------------------------------------------------------------------
int main()
{
const std::string a( "foo" ), b( "42.7" );
variant_grammar varGrammar;
MY_TYPE varA, varB;
auto begA = a.begin(), endA = a.end();
auto begB = b.begin(), endB = b.end();
qi::parse( begA, endA, varGrammar, varA );
qi::parse( begB, endB, varGrammar, varB );
if ( begA!=endA )
std::cerr << "A FAILED TO COMPLETELY PARSE" << std::endl;
if ( begB!=endB )
std::cerr << "B FAILED TO COMPLETELY PARSE" << std::endl;
std::string resultA, resultB;
my_visitor visitor1( resultA );
my_visitor visitor2( resultB );
#ifdef DO_VECTOR
std::for_each( varA.begin(), varA.end(), boost::apply_visitor( visitor1 ));
std::for_each( varB.begin(), varB.end(), boost::apply_visitor( visitor2 ));
#else
boost::apply_visitor( visitor1, varA );
boost::apply_visitor( visitor2, varB );
#endif
std::cout << resultA << std::endl;
std::cout << resultB << std::endl;
return 0;
}