diff --git a/src/backports/concepts.h b/src/backports/concepts.h index 3049c55c5c..e3998a4c8a 100644 --- a/src/backports/concepts.h +++ b/src/backports/concepts.h @@ -17,7 +17,10 @@ // resolution. // // `QL_CONCEPT_OR_TYPENAME(arg)`: expands to `arg` in C++20 mode, and to -// `typename` in C++17 mode. Example usage: +// `typename` in C++17 mode. +// +// `CPP_lambda(capture)(arg)(requires ...)`: Expands lambda to use +// `requires` in C++20 mode and `std::enable_if_t` in C++17 mode. // // Example usages: // @@ -29,15 +32,55 @@ // // `template ) T> void f(){...}` // +// `auto myLambda = CPP_lambda(someCapture)(someArg)(requires +// ranges::same_as) {...}` +// // NOTE: The macros are variadic to allow for commas in the argument, like in // the second example above. #ifdef QLEVER_CPP_17 #define QL_CONCEPT_OR_NOTHING(...) #define QL_CONCEPT_OR_TYPENAME(...) typename + +#define CPP_lambda CPP_lambda_sfinae + +#define CPP_LAMBDA_SFINAE_ARGS(...) \ + (__VA_ARGS__ CPP_LAMBDA_SFINAE_AUX_ + +#define CPP_LAMBDA_SFINAE_AUX_WHICH_(FIRST, ...) \ + CPP_PP_EVAL(CPP_PP_CHECK, CPP_PP_CAT(CPP_LAMBDA_SFINAE_PROBE_CONCEPT_, FIRST)) + +#define CPP_LAMBDA_SFINAE_AUX_(...) \ + CPP_PP_CAT(CPP_LAMBDA_SFINAE_AUX_, \ + CPP_LAMBDA_SFINAE_AUX_WHICH_(__VA_ARGS__, )) \ + (__VA_ARGS__) + +#define CPP_LAMBDA_SFINAE_AUX_0(...) , \ + std::enable_if_t< \ + CPP_PP_CAT(CPP_LAMBDA_SFINAE_AUX_3_, __VA_ARGS__) \ + >* = nullptr) + +#define CPP_lambda_sfinae(...) \ + CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN \ + [__VA_ARGS__] CPP_LAMBDA_SFINAE_ARGS + +#define CPP_LAMBDA_SFINAE_AUX_3_requires + #else #define QL_CONCEPT_OR_NOTHING(...) __VA_ARGS__ #define QL_CONCEPT_OR_TYPENAME(...) __VA_ARGS__ + +#define CPP_lambda(...) [__VA_ARGS__] CPP_LAMBDA_ARGS + +#define CPP_LAMBDA_ARGS(...) (__VA_ARGS__) CPP_LAMBDA_AUX_ + +#define CPP_LAMBDA_AUX_(...) \ + CPP_PP_CAT(CPP_LAMBDA_AUX_, CPP_LAMBDA_AUX_WHICH_(__VA_ARGS__, ))(__VA_ARGS__) + +#define CPP_LAMBDA_AUX_WHICH_(FIRST, ...) CPP_PP_EVAL(CPP_PP_CHECK, FIRST) + +#define CPP_LAMBDA_AUX_0(...) __VA_ARGS__ + #endif // The namespace `ql::concepts` includes concepts that are contained in the diff --git a/src/engine/sparqlExpressions/SparqlExpressionGenerators.h b/src/engine/sparqlExpressions/SparqlExpressionGenerators.h index d7332fd361..5b524818d9 100644 --- a/src/engine/sparqlExpressions/SparqlExpressionGenerators.h +++ b/src/engine/sparqlExpressions/SparqlExpressionGenerators.h @@ -105,20 +105,18 @@ CPP_template(typename Input, typename Transformation = std::identity)( /// Generate `numItems` many values from the `input` and apply the /// `valueGetter` to each of the values. -inline auto valueGetterGenerator = []( - size_t numElements, - EvaluationContext* context, - Input&& input, - ValueGetter&& valueGetter) { - CPP_assert(SingleExpressionResult); - auto transformation = [context, valueGetter](I&& i) - -> CPP_ret(decltype(valueGetter(AD_FWD(i), context)))( - requires ranges::invocable) { +inline auto valueGetterGenerator = CPP_lambda()( + size_t numElements, EvaluationContext* context, auto&& input, + auto&& valueGetter)(requires SingleExpressionResult) { + auto transformation = CPP_lambda(context, valueGetter)(auto&& i)( + requires ranges::invocable) { context->cancellationHandle_->throwIfCancelled(); return valueGetter(AD_FWD(i), context); }; - return makeGenerator(std::forward(input), numElements, context, - transformation); + + return makeGenerator(std::forward(input), numElements, + context, transformation); }; /// Do the following `numItems` times: Obtain the next elements e_1, ..., e_n