Boost Spirit x3 not compiling
Asked Answered
T

1

1

I'm following the x3 documentation on the boost website, and I've tried to augment the example on how to organize code with the stuff explained in the annotations example that comes after. I'm having the following error when compiling the project (either with g++ or MSVC):

error: no matching function for call to 'boost::spirit::x3::unused_type::get()'

In the first line of function on_success in the following code:

// tag used to get the position cache from the context
struct annotate_position
{
    template <typename T, typename Iterator, typename Context>
    inline void on_success(const Iterator &first, const Iterator &last, T &ast, const Context &context)
    {
        auto &position_cache = x3::get<position_cache_tag>(context).get();
        position_cache.annotate(ast, first, last);
    }
};

Code can be found here: Github.

The annotations example is almost the exact same code, just in a single file, so I can't figure out what's wrong...

Turner answered 30/7, 2019 at 0:33 Comment(0)
C
3

The annotation uses the with<> directive. That modifies the context for those rules.

The context, however, had been hard-coded in config.hpp because that enables the rule definitions to be separated in their own translation unit (source file).

To fix it directly:

struct position_cache_tag;
using position_cache = boost::spirit::x3::position_cache<std::vector<iterator_type>>;

using simple_context_type = x3::phrase_parse_context<x3::ascii::space_type>::type;

using context_type = boost::spirit::x3::context<
    client::parser::position_cache_tag,
    std::reference_wrapper<position_cache>, 
    simple_context_type
>;

That should already work. However, you'll find other things missing because the old parse function in main (without position annotations) was also still there. In principle adding a triplet like

BOOST_SPIRIT_INSTANTIATE(person_type, iterator_type, simple_context_type)
BOOST_SPIRIT_INSTANTIATE(employee_type, iterator_type, simple_context_type)
BOOST_SPIRIT_INSTANTIATE(employees_type, iterator_type, simple_context_type)

would be enough to alleviate, but then, obviously, the annotation code in on_success will not compile. If you want, you can SFINAE yourself out of that mess, but I just removed the unused code from main.cpp.

BONUS

As a bonus, you can do without the reference_wrapper these days, since I see you're using Boost 1.70.

The reference-wrapper used to be required for mutable state in with directives, but I found out recently (Spirit X3, Is this error handling approach useful?) that that's no longer required. Therefore you can simplify the context:

using context_type = boost::spirit::x3::context<
    client::parser::position_cache_tag,
    position_cache, 
    simple_context_type
>;

And drop the reference wrapper on both ends:

auto &position_cache = x3::get<position_cache_tag>(context); // NOTE: no more .get()

And

auto const parser =
    with<position_cache_tag>(positions)[client::employees()];

Full Code (Github)

Here's my working code: https://github.com/sehe/corrupted-spirit containing the following commits in order, so it's easy to find what changed why:

commit 2d1d553afab53d7a83620406c2dcd50967bf2765
Date:   Wed Jul 31 22:50:49 2019 +0200

    Build tweaks

    Make it compile on my linux box, and adding some minimum
    debug/sanitizer/diagnostics flags

commit 98a989bb165d0b25b6919449d4dd09f7656168c8
Date:   Wed Jul 31 22:51:50 2019 +0200

    Various compiler wanrings, no impact

commit 91f5c607c10a489e2d7b9e45dca55438d05419a2
Date:   Wed Jul 31 22:53:46 2019 +0200

    Fixed style issues in main.cpp

     - using namespace (my first hunch was with `ref` being std::ref instead
     of boost::ref, but that turned out a red herring. Better to be explicit
     though

     - added condition on use of ast[1]

commit 084700c80023d4fb291bee36f41cb99f23f7dffa
Date:   Wed Jul 31 22:51:20 2019 +0200

    Fix the context_type in config.hpp

commit df7f9505e042b93bcd62167090e89008788218de (HEAD -> master, sehe/master)
Date:   Wed Jul 31 22:56:20 2019 +0200

    Simplify the with directive

    1.70.0 no longer requires manual ref() for with directives with mutable
    context items.
Castellany answered 31/7, 2019 at 21:10 Comment(2)
Thanks for the reply by the way, I forgot to do it earlier. It helped me a bit to remember how to think of code in C++, which I haven't used for a while...Turner
I can imagine :) I forget the details of anything I don't use day to dayCastellany

© 2022 - 2024 — McMap. All rights reserved.