diff --git a/flang/docs/ParserCombinators.md b/flang/docs/ParserCombinators.md index 7cb77deba2197..076e76f703c49 100644 --- a/flang/docs/ParserCombinators.md +++ b/flang/docs/ParserCombinators.md @@ -141,7 +141,7 @@ collect the values that they return. * `applyLambda([](&&x){}, p1, p2, ...)` is the same thing, but for lambdas and other function objects. * `applyMem(mf, p1, p2, ...)` is the same thing, but invokes a member - function of the result of the first parser for updates in place. + function of the result of the first parser. ### Token Parsers Last, we have these basic parsers on which the actual grammar of the Fortran diff --git a/flang/lib/Parser/basic-parsers.h b/flang/lib/Parser/basic-parsers.h index 515b5993d6737..1a8c14e7048f6 100644 --- a/flang/lib/Parser/basic-parsers.h +++ b/flang/lib/Parser/basic-parsers.h @@ -580,11 +580,11 @@ template inline constexpr auto defaulted(PA p) { // applyLambda(f, ...) is the same concept extended to std::function<> functors. // It is not constexpr. // -// Member function application is supported by applyMem(f, a). If the -// parser a succeeds and returns some value ax, the result is that returned -// by ax.f(). Additional parser arguments can be specified to supply their -// results to the member function call, so applyMem(f, a, b) succeeds if -// both a and b do so and returns the result of calling ax.f(std::move(bx)). +// Member function application is supported by applyMem(&C::f, a). If the +// parser a succeeds and returns some value ax of type C, the result is that +// returned by ax.f(). Additional parser arguments can be specified to supply +// their results to the member function call, so applyMem(&C::f, a, b) succeeds +// if both a and b do so and returns the result of calling ax.f(std::move(bx)). // Runs a sequence of parsers until one fails or all have succeeded. // Collects their results in a std::tuple...>. @@ -654,39 +654,31 @@ inline /* not constexpr */ auto applyLambda( } // Member function application -template class AMFPHelper { - using resultType = typename OBJPARSER::resultType; - -public: - using type = void (resultType::*)(typename PARSER::resultType &&...); -}; -template -using ApplicableMemberFunctionPointer = - typename AMFPHelper::type; - -template -inline auto ApplyHelperMember( - ApplicableMemberFunctionPointer mfp, - ApplyArgs &&args, std::index_sequence) -> - typename OBJPARSER::resultType { - ((*std::get<0>(args)).*mfp)(std::move(*std::get(args))...); - return std::get<0>(std::move(args)); +template +inline auto ApplyHelperMember(MEMFUNC mfp, + ApplyArgs &&args, std::index_sequence) { + return ((*std::get<0>(args)).*mfp)(std::move(*std::get(args))...); } -template class ApplyMemberFunction { - using funcType = ApplicableMemberFunctionPointer; +template +class ApplyMemberFunction { + static_assert(std::is_member_function_pointer_v); + using funcType = MEMFUNC; public: - using resultType = typename OBJPARSER::resultType; + using resultType = + std::invoke_result_t; + constexpr ApplyMemberFunction(const ApplyMemberFunction &) = default; - constexpr ApplyMemberFunction(funcType f, OBJPARSER o, PARSER... p) + constexpr ApplyMemberFunction(MEMFUNC f, OBJPARSER o, PARSER... p) : function_{f}, parsers_{o, p...} {} std::optional Parse(ParseState &state) const { ApplyArgs results; using Sequence1 = std::index_sequence_for; using Sequence2 = std::index_sequence_for; if (ApplyHelperArgs(parsers_, results, state, Sequence1{})) { - return ApplyHelperMember( + return ApplyHelperMember( function_, std::move(results), Sequence2{}); } else { return std::nullopt; @@ -698,11 +690,11 @@ template class ApplyMemberFunction { const std::tuple parsers_; }; -template +template inline constexpr auto applyMem( - ApplicableMemberFunctionPointer mfp, - const OBJPARSER &objParser, PARSER... parser) { - return ApplyMemberFunction{mfp, objParser, parser...}; + MEMFUNC memfn, const OBJPARSER &objParser, PARSER... parser) { + return ApplyMemberFunction{ + memfn, objParser, parser...}; } // As is done with function application via applyFunction() above, class