c++ - Boost Spirit int into string rule -


assuming have following rule expecting string value should convert integer:

integer %=     attr_cast<int,std::string>(     lexeme[         -(char_('+') | char_('-')) >>         char_("1-9") >> *char_("0-9")     ]     )     ; 

so defined transformation structure:

template <> struct transform_attribute<int, std::string, qi::domain> {     // input type     typedef std::string& type;      static std::string pre(int & d) {         return "";     }     static void post(int & val, const type attr) {         val = boost::lexical_cast<int>(attr);     }     static void fail(int &) {} }; 

unfortunately expects convert int reference of left rule string reference (i removed reference operator not work). on internet saw examples working other way int string don't use references int. how can define proper transformation customly?

first off, don't have write this:

integer %= qi::int_; // job done 

next, write qi::attr_cast<std::string>(...) easier , more efficient doing as_string[ ... ].

next, if want parse ints laborious way, try this:

bool ok = parse(f, l,         (matches['-']  | -lit('+') >> attr(false)) [ phx::ref(negative) = _1 ] >> // sign         eps    [ _val = 0 ] >>         +digit [ _val *= 10, _val += (_1 - '0') ],         parsed); 

see live demo on coliru testing (u)int(8,16,32,64,max)_t on whole range:

the qi::int_parser<> template used above (via qi::int_) generalization of approach, more efficient.

now, can of course traits trick if insist:

namespace boost { namespace spirit { namespace traits {       template <typename int>         struct assign_to_attribute_from_value<             int,              std::string,             typename std::enable_if<std::is_integral<int>::value, void>::type // enabler             >         {             static void call(std::string const& val, int& attr) {                 //std::cout << __pretty_function__ << "('" << val << "')\n";                 attr = boost::lexical_cast<int>(val);             }         };  } } } 

now shooting fly canon. never mind boost::lexical_cast doesn't handle uint8_t , int8_t correctly purpose (treating them specially char , unsigned char?), had also hard code exception these:

// boost lexical_cast not usefully support `char` types integrals... (sic) template <>     struct assign_to_attribute_from_value<signed char, std::string> {         static void call(std::string const& val, signed char& attr) {             int tmp;             assign_to_attribute_from_value<int, std::string>::call(val, tmp);             attr = static_cast<signed char>(tmp);         }     };  template <>     struct assign_to_attribute_from_value<unsigned char, std::string> {         static void call(std::string const& val, unsigned char& attr) {             unsigned int tmp;             assign_to_attribute_from_value<unsigned int, std::string>::call(val, tmp);             attr = static_cast<unsigned char>(tmp);         }     }; 

now test cases passed with

    int parsed = 0;     bool ok = parse(f, l, as_string [ -char_("-+") >> +digit ], parsed); 

see live on coliru well.

now let me conclude "sane" approach: don't reinvent wheel

 int parsed = 0;  bool ok = qi::parse(f, l, qi::auto_, parsed); 

full program live on coliru

#include <boost/spirit/include/qi.hpp>  template <typename int> void do_test() {     (int const testcase : { std::numeric_limits<int>::min(), int(), std::numeric_limits<int>::max() }) {         auto const input = std::to_string(testcase);         auto f(input.begin()), l(input.end());           int parsed = 0;         bool ok = boost::spirit::qi::parse(f, l, boost::spirit::qi::auto_, parsed);          if (!ok || f!=l)             throw std::runtime_error("parse error");          std::cout << std::boolalpha << (testcase==parsed) << "\t" << testcase << " -> " << parsed << "\n";     } }  int main() {     do_test<int16_t>();  do_test<uint16_t>();     do_test<int32_t>();  do_test<uint32_t>();     do_test<int64_t>();  do_test<uint64_t>();     do_test<intmax_t>(); do_test<uintmax_t>(); } 

Comments

Popular posts from this blog

android - Get AccessToken using signpost OAuth without opening a browser (Two legged Oauth) -

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: mockito -

google shop client API returns 400 bad request error while adding an item -