Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 5967873
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 22, 20262026-05-22T20:00:26+00:00 2026-05-22T20:00:26+00:00

I’m using QI and Phoenix, and I want to write a small grammar that

  • 0

I’m using QI and Phoenix, and I want to write a small grammar that returns 4 bools which are to be used as arguments for a function call inside a semantic action.

I have several functions that need those things, and so far I have used this approach:

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

and while it’s okay on it’s own, using it all over the place is just plain ugly and confusing, even with ‘using’ the namespace parts.

That’s why I wanted to extract this expression into a standalone grammar.

So I tried this (credit goes to ildjarn for the 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();
}

That doesn’t compile unless fourBools[phx::bind(&noDice, spirit::_1)] is replaced with fourBools[phx::bind(&worksFine, spirit::_1)].

That means, my problem is the unpacking of arguments to match the signature of the function to be called, since the number of arguments differ at signature level (one tuple of four bools, vs four bools on their own).

Is it possible to unpack using phoenix placeholders directly, instead of writing wrappers which translate tuples into individual arguments for my existing functions that need them separate?
If it is, what would be the syntax for that?
After all, an inline version like ( qi::_bool >> qi::_bool >> qi::_bool >> qi::_bool) works fine when ‘unpacked’ by spirit::_1 - spirit::_4, placeholders.

That makes it appear to me as if this version returns a tuple as well, and is somehow unpackable with the above approach, unlike a grammar that returns one.

How do I deal with this?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-22T20:00:27+00:00Added an answer on May 22, 2026 at 8:00 pm

    It’s pretty much impossible to diagnose your issue if you don’t post a complete, coherent repro; it could be a syntax error, it could be a missing #include, who knows..?

    Here’s a working demonstration; hopefully you can use it as a reference to figure out what’s wrong with your code:

    ///// 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>
    
    typedef FourBools::attribute_type attr_t;
    
    struct verify_same
    {
        explicit verify_same(attr_t const& expected) : expected_(expected) { }
    
        void verify(attr_t const& actual) const
        {
            using boost::fusion::at_c;
    
            std::cout << std::boolalpha
                << "same as expected: " << (actual == expected_)
                << "\nactual values: "
                << at_c<0>(actual) << ' '
                << at_c<1>(actual) << ' '
                << at_c<2>(actual) << ' '
                << at_c<3>(actual) << '\n';
        }
    
    private:
        attr_t expected_;
    };
    
    int main()
    {
        namespace phx = boost::phoenix;
        namespace spirit = boost::spirit;
    
        std::string const input("4bools:true,true,true,false;");
        verify_same const vs(attr_t(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(&verify_same::verify, phx::cref(vs), spirit::_1)]
        );
        if (!success)
            std::cout << "parse() failed\n";
        else if (first != last)
            std::cout << "didn't consume all input\n";
        std::cout.flush();
    }
    

    As an aside, I think using a tuple with purely homogeneous types is strange; personally, I’d change the grammar’s synthesized attribute to boost::array<bool, 4>.


    EDIT (in response to OP’s edit): There’s good news and bad news and more good news.

    Here’s the good news: Boost.Fusion has functionality to do exactly what you want to do with minimal code: boost::fusion::fused<>. This will take a callable type (including free-function pointers and member-function pointers) that takes multiple arguments and wrap that callable type in a functor that takes a Fusion sequence; when this functor is invoked, it takes the Fusion sequence and unpacks it, forwarding the individual elements of the tuple to the wrapped callable type as separate arguments.

    So, given the grammar I already posted and the following:

    #include <string>
    #include <ios>
    #include <iostream>
    #include <boost/fusion/include/at_c.hpp>
    #include <boost/fusion/include/make_fused.hpp>
    #include <boost/spirit/include/phoenix_bind.hpp>
    #include <boost/spirit/include/phoenix_core.hpp>
    #include <boost/spirit/include/phoenix_fusion.hpp>
    #include <boost/spirit/include/qi_action.hpp>
    #include <boost/spirit/include/qi_parse.hpp>
    
    typedef FourBools::attribute_type attr_t;
    
    void free_func_taking_tuple(attr_t const& tup)
    {
        using boost::fusion::at_c;
    
        std::cout << std::boolalpha
            << "inside free_func_taking_tuple() :: "
            << at_c<0>(tup) << ' '
            << at_c<1>(tup) << ' '
            << at_c<2>(tup) << ' '
            << at_c<3>(tup) << '\n';
    }
    
    void free_func_taking_bools(
        bool const a, bool const b,
        bool const c, bool const d
    )
    {
        std::cout << std::boolalpha
            << "inside free_func_taking_bools() :: "
            << a << ' '
            << b << ' '
            << c << ' '
            << d << '\n';
    }
    

    boost::spirit::qi::parse() can be called like so:

    namespace phx = boost::phoenix;
    namespace spirit = boost::spirit;
    using boost::fusion::make_fused;
    
    // calls free_func_taking_tuple, nothing new here
    spirit::qi::parse(
        first, last,
        fourBools[phx::bind(free_func_taking_tuple, spirit::_1)]
    );
    
    // calls free_func_taking_bools, using boost::fusion::fused<> to unpack the tuple
    // into separate arguments
    spirit::qi::parse(
        first, last,
        fourBools[phx::bind(make_fused(&free_func_taking_bools), spirit::_1)]
    );
    

    Here’s the bad news: Boost.Fusion’s callable type wrappers rely on the TR1/C++11 result_of protocol, while Boost.Phoenix v2 implements the Boost.Lambda result_of protocol – these are not compatible. As a result, you must unpack the tuple elements yourself:

    namespace phx = boost::phoenix;
    namespace spirit = boost::spirit;
    
    spirit::qi::parse(
        first, last,
        fourBools[phx::bind(
            free_func_taking_bools,
            phx::at_c<0>(spirit::_1),
            phx::at_c<1>(spirit::_1),
            phx::at_c<2>(spirit::_1),
            phx::at_c<3>(spirit::_1)
        )]
    );
    

    Yuck! But, there’s more good news: Boost.Phoenix v3 is going to be released in Boost 1.47, and it implements the TR1/C++11 result_of protocol. Consequently, starting with Boost 1.47 you’ll be able to use boost::fusion::fused<> and save yourself some tedious boilerplate.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

No related questions found

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.