In Boost.Spirit one can read from a stream to a std::vector
simply by doing:
#include<vector>
#include<boost/spirit/include/qi.hpp>
namespace sqi = boost::spirit::qi;
int main(){
std::string const v_str = "AA BB CC";
std::vector<std::string> v;
auto it = begin(v_str);
bool r = sqi::phrase_parse(it, end(v_str),
(*sqi::lexeme[+sqi::char_("A-Z")]), sqi::space, v);
assert( v.size() == 3 and v[2] == "CC" );
}
However, it happens that I know the number of elements in advance because of the input format and I should be able to prereserve the space in the vector. For example if the input string is "3 AA BB CC", one can allocate in advance three elements.
The question is how to pass this extra information to the vector and optimize the later push_back
(e.g. avoiding reallocations).
What I tried was to parse an integer at the beginning at associate a semantic action to it where a reserve
is executed.
std::string const v_str = "3 AA BB CC";
std::vector<std::string> v;
auto it = begin(v_str);
bool r = sqi::phrase_parse(it, end(v_str),
sqi::int_[([&](int i){v.reserve(i);})] >>
(*sqi::lexeme[+sqi::char_("A-Z")]), sqi::space, v);
The problem is that the integer is not ignored after the semantic action and from my tests I can see that it tries to push the result (the 3
in the example) into the vector ever after reserve.
Another workaround would be to add another argument to phrase_parse
function but that seems to be an overkill.
So, how can I parse something in Boost.Spirit and only execute the semantic action without sending the result to the sink variable?
Even if this can be done I am not really sure if this is the right way to do it.