Boost :: Spirit :: Qi. Como transformar expressões de analisador embutidas em gramáticas independentes e como descompactar as tuplas geradas por elas?

Estou usando QI e Phoenix e quero escrever uma gramática pequena que retorne 4 bools que serão usados como argumentos para uma chamada de função dentro de uma ação semântic

Tenho várias funções que precisam dessas coisas e, até agora, usei essa abordagem:

( qi::_bool >>  qi::_bool >>  qi::_bool >>  qi::_bool)
[px::bind(&Bool4Function, spirit::_val, spirit::_1, spirit::_2, spirit::_3, spirit::_4)]

e enquanto estiver bem por si só, usá-lo em todo o lugar é simplesmente feio e confuso, mesmo com 'usando' as partes do espaço para nom

É por isso que eu queria extrair essa expressão em uma gramática independent

Então eu tentei isso (o crédito vai para ildjarn para o testbed):

///// grammar implementation /////
#include <boost/fusion/include/vector10.hpp>
#include <boost/spirit/include/qi_bool.hpp>
#include <boost/spirit/include/qi_char_.hpp>
#include <boost/spirit/include/qi_grammar.hpp>
#include <boost/spirit/include/qi_operator.hpp>
#include <boost/spirit/include/qi_rule.hpp>
#include <boost/spirit/include/qi_string.hpp>

struct FourBools : boost::spirit::qi::grammar<
    char const*,
    boost::fusion::vector4<bool, bool, bool, bool>()
>
{
    typedef boost::fusion::vector4<bool, bool, bool, bool> attribute_type;

    FourBools() : base_type(start_)
    {
        using boost::spirit::bool_;

        start_
            =   "4bools:"
            >> bool_ >> ','
            >> bool_ >> ','
            >> bool_ >> ','
            >> bool_ >> ';'
            ;
    }

private:
    boost::spirit::qi::rule<
        base_type::iterator_type,
        base_type::sig_type
    > start_;
};
FourBools const fourBools;


///// demonstration of use /////
#include <string>
#include <ios>
#include <iostream>
#include <boost/fusion/include/at_c.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/qi_action.hpp>
#include <boost/spirit/include/qi_parse.hpp>



void noDice(bool a, bool b, bool c, bool d) 
{

}

void worksFine(boost::fusion::vector4<bool, bool, bool, bool> a)
{

}
int main()
{
    namespace phx = boost::phoenix;
    namespace spirit = boost::spirit;

    std::string const input("4bools:true,true,true,false;");


    char const* first = input.c_str();
    char const* const last = first + input.size();
    bool const success = spirit::qi::parse(
        first, last,
        fourBools[phx::bind(&noDice, spirit::_1)]
    );


    if (!success)
        std::cout << "parse() failed\n";
    else if (first != last)
        std::cout << "didn't consume all input\n";
    std::cout.flush();
}

Isso não compila, a menos quefourBools[phx::bind(&noDice, spirit::_1)] é substituído porfourBools[phx::bind(&worksFine, spirit::_1)].

Isso significa, meu problema é descompactar argumentos para corresponder à assinatura da função a ser chamada, pois o número de argumentos difere no nível da assinatura (uma tupla de quatro bools e quatro bools por conta própria

É possível descompactar diretamente usando espaços reservados phoenix, em vez de escrever wrappers que convertem tuplas em argumentos individuais para minhas funções existentes que precisam delas separadas? Se for, qual seria a sintaxe para isso? Afinal, uma versão em linha como( qi::_bool >> qi::_bool >> qi::_bool >> qi::_bool) funciona bem quando 'descompactado' porspirit::_1 - spirit::_4, espaços reservados.

Faz parecer que esta versão também retorna uma tupla e é de alguma forma descompactável com a abordagem acima, diferente da gramática que retorna um

Como faço para lidar com isso?

questionAnswers(3)

yourAnswerToTheQuestion