提升精神:如何转换基本类型?

kfm*_*e04 4 c++ boost-spirit

假设我有一个std::string属性,但为了易于解析,我想使用qi::int_qi::double_.

有一种简单的方法可以将转换作为语义操作吗?

我试过这样的事情:

 std::stringstream ss; 
 my_int_as_str = qi::int_ [ ref(ss)<<_1; _val=ss.str() ];
Run Code Online (Sandbox Code Playgroud)

但这甚至不会编译.

编辑 - 尝试下面的回答

#include <iostream>
#include <string>
#include <vector>

#include <boost/spirit/include/qi.hpp>

namespace qi=boost::spirit::qi;
namespace phx=boost::phoenix;

int main(int argc, char* argv[])
{
    std::string test="123";
    std::string result;

    // 1. qi::raw[ qi::int_ ]       works
    // 2. qi::lexeme[ qi::int_ ]    doesn't
    // 3. qi::as_string[ qi::int_ ] doesn't
    qi::rule<std::string::const_iterator, std::string()> my_int_as_str = 
                   qi::raw[ qi::int_ ];
    parse( test.cbegin(), test.cend(), my_int_as_str, result );

    std::cout << result << std::endl;

    // -------------------------------------------------------------------------

    std::string test_vector="456 789";
    std::vector<std::string> result_vector;

    // 4. qi::raw[ qi::int_ ]       won't compile
    // 5. qi::lexeme[ qi::int_ ]    won't compile
    // 6. qi::as_string[ qi::int_ ] doesn't
    qi::rule<std::string::const_iterator,std::vector<std::string>(),qi::space_type> 
            my_int_as_str_vector = qi::lexeme[ qi::int_ ];

    phrase_parse(test_vector.cbegin(),test_vector.cend(),
            my_int_as_str_vector,qi::space,result_vector);

    for(auto& string: result_vector)
        std::cout << string << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

小智 6

您可以attr_cast通过专门transform_attribute为您的类型使用.

#include <iostream>
#include <string>
#include <vector>

#include <boost/spirit/include/qi.hpp>

namespace qi=boost::spirit::qi;
namespace phx=boost::phoenix;


namespace boost { namespace spirit { namespace traits
{

    template <>
    struct transform_attribute<std::string, int, qi::domain>
    {
        typedef int type;
        static int pre(std::string& d) { return 0; }//not useful in this case but required to avoid compiler errors
        static void post(std::string& val, int const& attr) //`val` is the "returned" string, `attr` is what int_ parses
        {
            std::stringstream ss;
            ss << attr;
            val= ss.str();
        }
        static void fail(std::string&) {}
    };
}}}

int main(int argc, char* argv[])
{
    std::string test="123";
    std::string test_vector="456 789";

    qi::rule<std::string::const_iterator,std::string()> my_int_as_str = qi::attr_cast(qi::int_);
    qi::rule<std::string::const_iterator,std::vector<std::string>(),qi::space_type> my_int_as_str_vector= *qi::attr_cast(qi::int_);

    std::string result;
    std::vector<std::string> result_vector;

    parse(test.cbegin(),test.cend(),my_int_as_str,result);
    phrase_parse(test_vector.cbegin(),test_vector.cend(),my_int_as_str_vector,qi::space,result_vector);


    std::cout << result << std::endl;
    for(auto& string: result_vector)
        std::cout << string << std::endl;


    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果你真的需要/想要使用语义动作,最简单的替代方法是定义一个以int作为参数并返回一个字符串的函数(这比attr_cast替代方法更简单但它也更慢,几乎是我真正简单基准测试的两倍时间):

std::string semantic_transform(int i)
{
    std::stringstream ss;
    ss<<i;
    return ss.str();
}
...
std::string string_semantic;
qi::parse(test.cbegin(),test.cend(),qi::int_[&semantic_transform],string_semantic);
std::cout << string_semantic << std::endl;
Run Code Online (Sandbox Code Playgroud)


seh*_*ehe 6

建筑方式:

qi::rule<Iterator, std::string()> my_int_as_str = 
       qi::as_string [ qi::int_ ];
Run Code Online (Sandbox Code Playgroud)

对于这个特殊的简单情况,qi::rawqi::lexeme会工作同样出色,因为它们都暴露源迭代器对,其内置分配到属性std::string

阐述:

my_int_as_str = qi::lexeme [ qi::int_ ]; // equivalent
my_int_as_str = qi::raw [ qi::int_ ];    // idem
Run Code Online (Sandbox Code Playgroud)

  • 显然,大多数差异是由于使用了stringstream([有趣的博客](http://tinodidriksen.com/2010/02/07/cpp-convert-int-to-string-speed/)).如果我将`post`函数的内容更改为`karma :: generate(std :: back_inserter(val),karma :: int_,attr);`时间是可比的(仍然比`qi :: raw慢一点`,但比原来快得多). (2认同)