Q:

Boost spirit x3 parser doesn't work with multiple attribute

The Spirit X3 parser function works well using 1 attribut. When I try to compile the code from the documentation with multiple attribute, it doesn't work. 
#include <boost/spirit/home/x3.hpp>
#include <iostream>
using namespace std;
using namespace boost::spirit;

string a = "3.2 4.5";
auto begin = a.begin();
auto end = a.end();
double d1 = 0.0, d2 = 0.0;
x3::phrase_parse(begin, end ,
                 x3::double_ >> x3::double_,
                 x3::space,
                 d1, d2);  // doesn't work. Accept only 1 attribut

It returns me the following error : 
/home/sacha/Dev/vql/vqlcompiler.cpp:20: erreur : no matching function for call to ‘phrase_parse(__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, boost::spirit::x3::sequence<boost::spirit::x3::real_parser<double>, boost::spirit::x3::real_parser<double> >, const space_type&, double&, double&)’
                      x3::double_ >> x3::double_, x3::space, d1, d2);
                                                                   ^

Seems it's not a variadic template. So, is it me or the documentation ? 

A:

Indeed. In X3 the variadic overload was dropped.
I wager this was part of a general regime of removing unnecessary complications from the design since Spirit V2.
Of course you can easily wrap one up yourself:
auto parse = [](auto& b, auto e, auto const& p, auto&... binds) {
    auto attr = std::tie(binds...);
    return x3::phrase_parse(b, e, p, x3::space, attr);
};

Demo
Live On Coliru
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/spirit/home/x3.hpp>
#include <iostream>

namespace x3 = boost::spirit::x3;

int main() {
    auto parse = [](auto& b, auto e, auto const& p, auto&... binds) {
        auto attr = std::tie(binds...);
        return x3::phrase_parse(b, e, p, x3::space, attr);
    };

    std::string const s = "3.2 4.5";

    double d1, d2;
    auto begin = s.begin(), end = s.end();

    if (parse(begin, end, x3::double_ >> x3::double_, d1, d2)) {
        std::cout << "Parsed: " << d1 << ", " << d2 << "\n";
    } else {
        std::cout << "Parse failed\n";
    }

    if (begin != end)
        std::cout << "Remaining unparsed input: '" << std::string(begin, end) << "'\n";
}

Prints
Parsed: 3.2, 4.5

