вместо этого, потому что кортеж состоит исключительно из однородных типов. Это поведение называется «разрушение атрибутов» в документах Духа.

ользую QI и Phoenix, и я хочу написать небольшую грамматику, которая возвращает 4 bools, которые должны использоваться в качестве аргументов для вызова функции внутри семантического действия.

У меня есть несколько функций, которые нуждаются в этих вещах, и до сих пор я использовал этот подход:

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

и хотя все в порядке само по себе, его повсеместное использование просто уродливо и запутанно, даже с «использованием» частей пространства имен.

Вот почему я хотел извлечь это выражение в отдельную грамматику.

Поэтому я попробовал это (кредит идет на ildjarn для испытательного стенда):

///// 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();
}

Это не компилируется, еслиfourBools[phx::bind(&noDice, spirit::_1)] заменяется наfourBools[phx::bind(&worksFine, spirit::_1)].

Это означает, что моя проблема заключается в распаковке аргументов, соответствующих сигнатуре вызываемой функции, так как количество аргументов различается на уровне сигнатуры (один кортеж из четырех bools против четырех bools самостоятельно).

Можно ли распаковать, используя заполнители phoenix напрямую, вместо того, чтобы писать обертки, которые переводят кортежи в отдельные аргументы для моих существующих функций, которым они нужны отдельно? Если это так, какой будет синтаксис для этого? В конце концов, встроенная версия, как( qi::_bool >> qi::_bool >> qi::_bool >> qi::_bool) отлично работает при распаковкеspirit::_1 - spirit::_4, заполнители.

Это заставляет меня выглядеть так, как будто эта версия также возвращает кортеж и каким-то образом не распаковывается с помощью описанного выше подхода, в отличие от грамматики, которая ее возвращает.

Как мне с этим бороться?

Ответы на вопрос(3)

Ваш ответ на вопрос