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

C++ 提升精神:如何转换基本类型?,c++,boost-spirit,C++,Boost Spirit,假设我有一个std::string属性,但为了便于解析,我想使用qi::int或qi::double 有没有一种简单的方法可以将转换作为语义动作来执行 我试过这样的方法: std::stringstream ss; my_int_as_str = qi::int_ [ ref(ss)<<_1; _val=ss.str() ]; std::stringstream-ss; my_int_as_str=qi::int[ref(ss)您可以通过专门化您的类型来使用 #include

假设我有一个
std::string
属性,但为了便于解析,我想使用
qi::int
qi::double

有没有一种简单的方法可以将转换作为语义动作来执行

我试过这样的方法:

 std::stringstream ss; 
 my_int_as_str = qi::int_ [ ref(ss)<<_1; _val=ss.str() ];
std::stringstream-ss;
my_int_as_str=qi::int[ref(ss)您可以通过专门化您的类型来使用

#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;
}
内置方式:

qi::rule<Iterator, std::string()> my_int_as_str = 
       qi::as_string [ qi::int_ ];

非常好-tyvm提供了详细的答案(基准评论也很好了解)+1获取大量优秀的信息和技术。然而,对于这项特殊任务,我更喜欢我自己的答案:)+1哇-这更好-你能用一个例子详细说明你的
qi::raw
qi::lexeme
注释吗?我将试用你的示例-ty.ty-我尝试了6种方法(如字符串、lexeme、raw)(std::string,std::vector)我唯一能用std::string处理的是raw。这三者之间肯定有一些细微的区别(代码在OP edit中)…我将尝试用qi::raw搜索一些文档。+1。它更简单,速度也更快(msvc11快40倍以上,g++4.7.1快8倍左右)。其他选项与我的_int_as_str=qi::int_一样,将int转换为char({)。显然,大部分差异是由于使用了stringstream()。如果我将
post
函数的内容更改为
karma::generate(std::back_inserter(val),karma::int,attr);
则时间相当(仍然比
qi::raw
稍慢一点,但比原始版本快得多)@llonesmiz查看Karma vs.sstream的性能。当然
qi::raw
应该是最快的,因为它不进行转换。如果您可以使用
+qi::digit
来代替,它会更快。要获得出色的性能,您只需返回
boost::iterator_对
并延迟字符串的构造(假设是前向迭代器,而不是输入迭代器)。这基本上就是Spirit Lex对令牌所做的。
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;
qi::rule<Iterator, std::string()> my_int_as_str = 
       qi::as_string [ qi::int_ ];
my_int_as_str = qi::lexeme [ qi::int_ ]; // equivalent
my_int_as_str = qi::raw [ qi::int_ ];    // idem