Type safety of Boost Qi/X3 parse

Viewed 208

Consider this code using Boost Spirit X3 (conceptually same goes for Boost Spirit Qi):

  string command;
  string value;
  x3::parse(command.begin(), command.end(), "float:" >> x3::double_, value);

Why is this code not generating any error during compilation? Shouldn't "float:" >> x3::double_ parser have attribute of type double and therefore not accept std::string as 4th argument to parse?

BTW, I know I could do this:

string value;
auto assign = [](auto& ctx){value = _attr(ctx)};
x3::parse(command.begin(), command.end(), "float:" >> x3::double_[assign], value)

which would generate an error, but it is more complicated than necessary.

As a last resort: any there any well-known replacements for sscanf that would be type safe (possibly in boost)?

2 Answers

It's because automatic attribute propagation into a container is very flexible.

And std::string is a container.

Perhaps if we do the following experiment it makes a bit more sense:

Live On Coliru

#include <boost/spirit/home/x3.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;

int main() {
    //std::string command = "f: hello world";
    std::string command = "f: 104 101 108 108 111 32 119 111 114 108 100";
    std::string value;
    x3::phrase_parse(
            command.begin(),
            command.end(),
            "f:" >> *x3::double_, x3::blank,
            value);

    std::cout << value << "\n";
}

As you might surmise, it prints:

hello world

For strings this seems surprising. It would be much less of a surprise if the target was std::vector<float> - but it would require precisely the same amount of conversions.

It's fair for each element to enjoy propagation conversions. What if you were parsing Ast nodes like:

struct Operation {
     Operator op;
     std::vector<Expression> operands;
}

You would hate if operands didn't implicitly convert into Expression from Unary, FunctionCall, StringLiteral etc.

@tomasz-grobelny, using the explicit_convert_parser_type from here, and with #defined REPRODUCE_SO_62986317, correctly compile-time errors when passing anything but a double as the attribute.

HTH,

Larry

Related