foonathan/lexy

problem with `lexy::callback_with_state`

rkaminsk opened this issue · 3 comments

The helper lexy::callback_with_state fails to compile if not both a version with and without state for each possible overload is given. As a quick hack, I applied the patch below to get things to compile. Not sure how ho fix this properly.

diff --git a/include/lexy/callback/adapter.hpp b/include/lexy/callback/adapter.hpp
index d81dd2fa..cb48d60f 100644
--- a/include/lexy/callback/adapter.hpp
+++ b/include/lexy/callback/adapter.hpp
@@ -4,6 +4,8 @@
 #ifndef LEXY_CALLBACK_ADAPTER_HPP_INCLUDED
 #define LEXY_CALLBACK_ADAPTER_HPP_INCLUDED
 
+#include <stdexcept>
+
 #include <lexy/callback/base.hpp>
 
 namespace lexy
@@ -34,6 +36,13 @@ struct _callback_with_state : _overloaded<Fns...>
         }
     };
 
+    template <typename... Args>
+    constexpr return_type operator()(Args&&... args) const&& {
+        (static_cast<void>(args), ...);
+        throw std::runtime_error("no state given");
+    }
+    using _fn_as_base<Fns>::operator()...;
+
     constexpr explicit _callback_with_state(Fns... fns) : _overloaded<Fns...>(LEXY_MOV(fns)...) {}
 
     template <typename State>

Can you clarify what your problem is?

I would expect the following example to compile without giving the unused overload.

#include <stdexcept>
#include <iostream>

#include <lexy/callback.hpp>
#include <lexy/dsl.hpp>
#include <lexy/action/parse.hpp>
#include <lexy/input/string_input.hpp>

namespace grammar {

struct example_prod {
    static constexpr auto rule = LEXY_LIT("x");
    static constexpr auto value = lexy::callback_with_state<void>(
        []() {
            throw std::runtime_error("never called but required");
        },
        [](int &state) {
            state += 1;
        }
    );
};

}

int main() {
    auto in = lexy::zstring_input("xx");
    int state = 10;
    auto res = lexy::parse<grammar::example_prod>(in, state, lexy::noop);
    std::cout << "value: " << state << std::endl;
}

Fixed.