-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Backport C++20 concepts to C++17 in the 'sparqlExpressions' module #1787
Backport C++20 concepts to C++17 in the 'sparqlExpressions' module #1787
Conversation
Hi @joka921 Here is the |
ValueGetter&& valueGetter) { | ||
CPP_assert(SingleExpressionResult<Input>); | ||
auto transformation = [context, valueGetter]<typename I>(I&& i) | ||
-> CPP_ret(decltype(valueGetter(AD_FWD(i), context)))( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason, clang17 and older cause the compiler to crash if the return type is explicitly defined in nested lambda.
Clang18 compiles it correctly.
It looks like a bug in older compilator version.
auto transformation = [context, valueGetter]<typename I>(I&& i) | ||
-> CPP_ret(decltype(valueGetter(AD_FWD(i), context)))( | ||
requires ranges::invocable<ValueGetter, I&&, EvaluationContext*>) { | ||
inline auto valueGetterGenerator = CPP_lambda()( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joka921
To solve the clang crash for lambdas mentioned previously I added the CPP_lambda
macro which expands to requires
in C++20 and std::enable_if_t
(as additional lambda argument) in C++17.
What do you think about it? It can be used instead of CPP_assert
in other lambdas.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I like the CPP_lambda
macro, feel free to use it in the other places,
but the CPP_assert
s are also fine in the many places where there is no overload resolution happening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice, I have some suggestions and some open questions, partly also for myself.
I suggest that you read my comments and make another pass with the things you think are appropriate, and then you ping me again and I make a final pass with the small cleanups and the merging together etc.
src/backports/concepts.h
Outdated
#define CPP_LAMBDA_AUX_WHICH_(FIRST, ...) CPP_PP_EVAL(CPP_PP_CHECK, FIRST) | ||
|
||
#define CPP_LAMBDA_AUX_0(...) __VA_ARGS__ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea very much, I also have added some additional macros in another branch and will consolidate them when merging (in particular I have opened a several file for the internal SFINAE_AUX_WHICH_BLA_...
macros.
src/engine/GroupBy.cpp
Outdated
CPP_assert(sparqlExpression::SingleExpressionResult<T> && | ||
VectorOfAggregationData<A>); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest two separate CPP_assert()
for &&
, because then you get better diagnostics in the failure case.
src/engine/LazyGroupBy.cpp
Outdated
&evaluationContext]<sparqlExpression::SingleExpressionResult T>( | ||
[blockSize, &evaluationContext]<typename T>( | ||
VectorOfAggregationData auto& aggregateData, T&& singleResult) { | ||
CPP_assert(sparqlExpression::SingleExpressionResult<T>); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that you have it, you can consider rewriting the CPP-asser
with CPP_lambda
,but I am also fine with the assert
s in places where we don't need overload resolution. Just let me know how you decide.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I decided to use CPP_lambda instead of CPP_assert but not all. I keep CPP_assert where we have template parameter packs at this moment. We need to somehow deal with the lambda explicit template parameter list to be compatible with C++17.
if constexpr (ranges::invocable<decltype(aggregateOperation._function), | ||
decltype(AD_FWD(x)), | ||
decltype(AD_FWD(y))>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you give the X
and Y
names in the lambda declaration, then this is
ranges::invocable<AggregateOperation, X&&, Y&&>
This is more readable then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean X
, and Y
as lambda template parameters?
However, the problem is that the lambda explicit template parameter list has been available since C++20.
So later we need to somehow deal with this to be compatible with C++17.
auto transformation = [context, valueGetter]<typename I>(I&& i) | ||
-> CPP_ret(decltype(valueGetter(AD_FWD(i), context)))( | ||
requires ranges::invocable<ValueGetter, I&&, EvaluationContext*>) { | ||
inline auto valueGetterGenerator = CPP_lambda()( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I like the CPP_lambda
macro, feel free to use it in the other places,
but the CPP_assert
s are also fine in the many places where there is no overload resolution happening.
|
||
// Ensures that T is a floating-point type. | ||
template <typename T> | ||
CPP_concept FloatingPoint = std::is_floating_point_v<T>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still have to figure out where to put them and what to name them.
I think I already have a file src/backports/concepts.h
where I want a common namespace for the concepts that are in C++20.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1787 +/- ##
==========================================
+ Coverage 90.02% 90.03% +0.01%
==========================================
Files 396 396
Lines 37974 37989 +15
Branches 4262 4262
==========================================
+ Hits 34185 34203 +18
+ Misses 2493 2491 -2
+ Partials 1296 1295 -1 ☔ View full report in Codecov by Sentry. |
90b077e
to
3c6751b
Compare
@joka921 Thank you for your feedback! |
…essions' into cxx17_concepts_sparqlExpressions # Conflicts: # src/backports/concepts.h # src/engine/Bind.cpp # src/engine/Filter.cpp # src/engine/GroupBy.cpp # src/engine/LazyGroupBy.cpp # src/engine/sparqlExpressions/AggregateExpression.h # src/engine/sparqlExpressions/ConditionalExpressions.cpp # src/engine/sparqlExpressions/SparqlExpressionGenerators.h # src/engine/sparqlExpressions/SparqlExpressionTypes.h # src/engine/sparqlExpressions/StringExpressions.cpp
# Conflicts: # src/backports/concepts.h
Signed-off-by: Johannes Kalmbach <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much.
I have merged this with the master, make sure to git pull
before continuing.
We now have the following additional macro:
CPP_template_lambda(captures)(typename T)(T&& arg) (requires SingleExpressionResult<T>)
,
Please consistently use it for the places where it helps (I have marked them).
Also add the missing macro CPP_template_lambda_mut
(the same but with mutable
),
and use it in the places I marked accordingly.
For the macro implementation, please follow the style I now chose: The internal BLA_BLAJ_AUX_WHICH_
macros come into the internal CPPtemplate2.h
file, and only the final exposition + the documentation is done in the user-facing concepts.h
folder.
That should then be the final iteration for this PR.
Let me know if I can be of additional assistance.
src/engine/Bind.cpp
Outdated
constexpr static bool isVariable = std::is_same_v<T, ::Variable>; | ||
constexpr static bool isStrongId = std::is_same_v<T, Id>; | ||
auto visitor = CPP_lambda_mut(&)(auto&& singleResult)( | ||
requires sparqlExpression::SingleExpressionResult< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The deacy_t
is not needed, and maybe CPP_template_lambda_mut
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At least get rid of all the decltype(singleResult
) below.
src/engine/Filter.cpp
Outdated
std::decay_t<decltype(singleResult)>>) { | ||
if constexpr (std::is_same_v<std::decay_t<decltype(singleResult)>, | ||
ad_utility::SetOfIntervals>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CPP_template_lambda
src/engine/GroupBy.cpp
Outdated
auto visitor = CPP_lambda_mut(&)(auto&& singleResult)( | ||
requires sparqlExpression::SingleExpressionResult< | ||
std::decay_t<decltype(singleResult)>>) { | ||
constexpr static bool isStrongId = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CPP_template_lambda_mut
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- then replace all the
decltype(...)s
below.
src/engine/GroupBy.cpp
Outdated
&outCol]<sparqlExpression::SingleExpressionResult T>( | ||
T&& singleResult) mutable { | ||
auto visitor = CPP_lambda_mut(&evaluationContext, &resultTable, &localVocab, | ||
&outCol)(auto&& singleResult)( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
auto visitConstantExpressionResult = CPP_lambda( | ||
&nextUnboundIndices, &unboundIndices, &isUnbound, &result, | ||
ctx)(auto&& childResult)( | ||
requires SingleExpressionResult<std::decay_t<decltype(childResult)>> && | ||
isConstantResult<std::decay_t<decltype(childResult)>>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CPP_template_lambda
CPP_lambda(&result, &unboundIndices, &nextUnboundIndices, &ctx, | ||
&isUnbound)(auto&& childResult)(requires CPP_NOT( | ||
isConstantResult<std::decay_t<decltype(childResult)>> && | ||
SingleExpressionResult<std::decay_t<decltype(childResult)>> && | ||
std::is_rvalue_reference_v<decltype(childResult)>)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CPP_template_lambda
auto visitExpressionResult = CPP_lambda( | ||
&visitConstantExpressionResult, | ||
&visitVectorExpressionResult)(auto&& childResult)( | ||
requires SingleExpressionResult<std::decay_t<decltype(childResult)>> && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CPP_template_lambda
CPP_lambda()(size_t numElements, EvaluationContext* context, auto&& input, | ||
auto&& valueGetter)( | ||
requires SingleExpressionResult<std::decay_t<decltype(input)>>) { | ||
auto transformation = CPP_lambda(context, valueGetter)(auto&& i)( | ||
requires ranges::invocable<std::decay_t<decltype(valueGetter)>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CPP_template_lambda
requires std::is_rvalue_reference_v<T&&> { | ||
if constexpr (isConstantResult<T>) { | ||
auto visitSingleExpressionResult = CPP_lambda(&ctx, &result)(auto&& s)( | ||
requires SingleExpressionResult<std::decay_t<decltype(s)>> && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CPP_template_lambda
I now see your Comment about |
I used CPP_template_lambda macros as you suggested. |
Conformance check passed ✅No test result changes. |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much, this looks nice and clean now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, that looks great now
The backport is implemented using macros from Eric Niebler's
range-v3
library.