Library: implement model-binding with generic-λ
Basically the implementation is already in place; yet for better error messages we need to find out if the given functor can handle the model present at this stage. Since generic-λ are not functions by themselves (but rather templates), we need to ''probe'' with the expected argument and see if instantiation is possible. ⚠ NOTE: still a strange bug related to using the same Syntax several times
This commit is contained in:
parent
860e2fa226
commit
57dc56f5c6
3 changed files with 54 additions and 39 deletions
|
|
@ -168,23 +168,21 @@ namespace util {
|
|||
|
||||
|
||||
|
||||
// namespace {
|
||||
// /** handle all regular "function-like" entities */
|
||||
// template<typename SRC, typename F, typename SEL =void>
|
||||
// struct FunDetector
|
||||
// {
|
||||
// using Sig = typename _Fun<F>::Sig;
|
||||
// };
|
||||
//
|
||||
// /** handle a generic lambda, accepting a reference to the `SRC` iterator */
|
||||
// template<typename SRC, typename F>
|
||||
// struct FunDetector<SRC, F, lib::meta::disable_if<_Fun<F>> >
|
||||
// {
|
||||
// using Arg = std::add_lvalue_reference_t<SRC>;
|
||||
// using Ret = decltype(std::declval<F>() (std::declval<Arg>()));
|
||||
// using Sig = Ret(Arg);
|
||||
// };
|
||||
// }
|
||||
namespace {
|
||||
/** helper to detect return type of a possibly generic λ */
|
||||
template<typename ARG, typename FUN, typename SEL =void>
|
||||
struct _ProbeFunReturn
|
||||
{
|
||||
static_assert (!sizeof(ARG),
|
||||
"Model binding must accept preceding model result.");
|
||||
};
|
||||
|
||||
template<typename ARG, typename FUN>
|
||||
struct _ProbeFunReturn<ARG,FUN, std::void_t<decltype(std::declval<FUN>() (std::declval<ARG>()))>>
|
||||
{ // probe the λ with ARG to force template instantiation
|
||||
using Ret = decltype(std::declval<FUN>() (std::declval<ARG>()));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapt by applying a result-transforming function after a successful parse.
|
||||
|
|
@ -197,12 +195,8 @@ namespace util {
|
|||
adaptConnex (CON&& connex, BIND&& modelBinding)
|
||||
{
|
||||
using RX = typename CON::Result;
|
||||
// using Arg = lib::meta::_FunArg<BIND>;
|
||||
// static_assert (std::is_constructible_v<Arg,RX>,
|
||||
// "Model binding must accept preceding model result.");
|
||||
// using AdaptedRes = typename _Fun<BIND>::Ret;
|
||||
using Arg = std::add_lvalue_reference_t<RX>;
|
||||
using AdaptedRes = decltype(modelBinding (std::declval<Arg>() ));
|
||||
using Arg = std::add_rvalue_reference_t<RX>;
|
||||
using AdaptedRes = typename _ProbeFunReturn<Arg,BIND>::Ret;
|
||||
return Connex{[origConnex = forward<CON>(connex)
|
||||
,binding = forward<BIND>(modelBinding)
|
||||
]
|
||||
|
|
@ -217,6 +211,7 @@ namespace util {
|
|||
}
|
||||
|
||||
|
||||
|
||||
/* ===== building structured models ===== */
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -573,7 +573,6 @@ namespace test {
|
|||
auto syntax1 = accept(word).seq(word)
|
||||
.bind([](Mod1 res)
|
||||
{
|
||||
// auto& [a,b] = res;
|
||||
return res.get<0>().str() +"-"+ res.get<1>().str();
|
||||
});
|
||||
|
||||
|
|
@ -582,10 +581,22 @@ namespace test {
|
|||
syntax1.parse(s1);
|
||||
CHECK (syntax1.success());
|
||||
auto res1 = syntax1.getResult();
|
||||
SHOW_TYPE(decltype(res1))
|
||||
CHECK (showType<decltype(res1)>() == "string");
|
||||
SHOW_EXPR(res1)
|
||||
CHECK (res == "ham-actor"_expect);
|
||||
CHECK (showType<decltype(res1)>() == "string"); // surprise! it is a simple string (as returned from λ)
|
||||
CHECK (res1 == "ham-actor"_expect);
|
||||
|
||||
// 💡 shortcut for RegExp match groups...
|
||||
auto syntax1b = accept("(\\w+) (\\w+)");
|
||||
CHECK (accept(syntax1b).bindMatch( ).parse(s1).getResult() == "ham actor"_expect );
|
||||
CHECK (accept(syntax1b).bindMatch(1).parse(s1).getResult() == "ham"_expect );
|
||||
CHECK (accept(syntax1b).bindMatch(2).parse(s1).getResult() == "actor"_expect );
|
||||
CHECK (accept(syntax1b).bindMatch(3).parse(s1).getResult() == ""_expect );
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue