-
Notifications
You must be signed in to change notification settings - Fork 82
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
[FEATURE] Adds all_of traits for type list and parameter packs. #1214
Conversation
Without looking too much into it, it seems similar to std::conjunction but more flexible. |
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 have some general design concerns, maybe also because I have more of the type_list stuff laid out in my head than is written in code already.
In general I had planned:
pack_traits::apply (takes a transformation trait, applies to every element) [in #1215 ]
pack_traits::apply_v (takes a type trait, applies to every element) [naming not clear yet]
Other names for these could be pack_traits::transform. Or one could use that for something else.
What your proposal does is in fact running an arbitrary function on some values, with the exception that those values are previously constructed from types. With the purpose of later passing a lambda that also actually doesn't to anything other than evaluating a type property.
This is switching between type-space and value-space quite often which is not easy to understand and likely also not the best thing for compiler performance (although I am not sure about it).
I see that we might want the ability to run lambdas on a type list, but I would prefer if we can discuss the general design before blowing it up.
Can you do one of the simpler temporary solutions for #863 like defining a concept and immediately expanding on that?
{ | ||
return false; | ||
} | ||
//!\endcond |
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.
Currently the design is that traits should either SFINAE or fail if instantiating them fails. Adding another possibility of "silently working" make this more complicated.
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.
Not sure, what you mean but if I have something that does not SFINAE on an instantiation failure and is still ill-formed it will fail. It's only that you can use in addition SFINAE and do not provide a default case for every trait to test.
1053361
to
4678c39
Compare
Codecov Report
@@ Coverage Diff @@
## master #1214 +/- ##
=========================================
Coverage ? 97.59%
=========================================
Files ? 220
Lines ? 8956
Branches ? 0
=========================================
Hits ? 8741
Misses ? 215
Partials ? 0
Continue to review full report at Codecov.
|
Besides that apply means to invoke a function on all arguments and not element wise, we will likely add more algorithms on types because they are useful in many places. At least that is what I had planned.
Well, I can't be sure either but it looks like that the compiler will not not have problems optimizing this. Anyway, if performance is your biggest concern we need to use a third library from people that have spent a good time optimising this. In general, this is so much easier than the pure type based approach and closer to modern c++. You don't need to pollute the namespace with helper structs as you can directly call it in the compile time expression with a lambda. Once we have template names it will become even more easier with lambdas because you don't need the decltype anymore. It is a generic solution that can be used in type and value land.
Absolutely. Never meant to be the absolute and final design. It is a first proposal that in my opinion is close to the use of standard algorithms and therefor has a major advantage over designs where I need to provide template member types in structs that evaluate to bool_constant types based on SFINAE or constraints.
Sure. |
ad6b4c8
to
2952562
Compare
So I moved the functionality to core/detail/pack_algorithm and also moved the already existing for_each functionality to this file. |
16a46f2
to
76af1e6
Compare
@smehringer ping |
Travis was failing so I did not review this before |
you can ignore jenkins for this PR. |
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.
You introduce code in commit 1 & 2 that you delete again in commit 3. I guess you plan to squash this or ? It if confusing to review commit by commit because it is hard to track if there are other changes than those of altering your feature again. It would be nice if you split these changes from the feature.
I did not review type traits that often so I am a littel confused about the naming.
When do we call something _type
? (all_of_type)
@@ -30,27 +30,27 @@ int main() | |||
static_assert(std::is_same_v<id_t, std::type_identity<type>>, "id is of type std::type_identity<type>"); | |||
|
|||
if constexpr(std::is_same_v<type, bool>) | |||
debug_stream << "bool"; | |||
seqan3::debug_stream << "bool"; |
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.
remove using namespace seqan3;
in line 8
@@ -0,0 +1,54 @@ | |||
#include <iostream> |
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.
you are using debug stream, do you need this include?
yes. I'll squash this.
Well, we need to somehow distinguish all_of for type lists and parameter packs since we do not use different namespaces as it is done in the type_list traits at the moment. Accordingly, the |
Ugh... But we usually put |
This was already introduced for |
c61b57d
to
5506dab
Compare
I agree that if it is strictly detail it's not worth a lengthy discussion. |
@smehringer ping |
I was waiting for an answer but I guess this means you disagree? |
since I am second reviewer now maybe someone else should review this first |
5506dab
to
b90611f
Compare
@marehr ping |
Sorry for the late response, I have the feeling that this PR would be best discussed in person. |
Ok, then please put it on the card for next Monday discussion. I do agree that we need to be certain about the design and that here are multiple cornerstones here. |
Yep. I added a card https://github.com/orgs/seqan/projects/4#card-26492576 |
2dfd2dd
to
9f5fe60
Compare
@rrahn What's the status here? |
@joshuak94 I am waiting on the review, From POV this is done. |
e3ae56b
to
89f5e47
Compare
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.The code looks good to me. Just some smaller and sometimes a tiny bit bigger smaller naming and documentation stuff, as well as proposal to remove tuple support. 🤸♀️ Took me longer than 1am xD
89f5e47
to
af042b6
Compare
af042b6
to
e620aa1
Compare
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.
This is a very happy @marehr; Just some little tiny stuff left.
e620aa1
to
a6b3f61
Compare
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.
😽 LGTM 💋
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.
some minor stuff
// all_of | ||
//----------------------------------------------------------------------------- | ||
|
||
/*!\brief Tests whether a given predicate evaluates to `true` for each element in a parameter pack. |
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.
This may be just personal flavour, but you do not call this function by passing a parameter pack but you call it by passing a variable number of values? You just use the parameter pack to capture this. Or am I wrong?
So this description might be misleading?
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.
A function parameter pack is a function parameter that accepts zero or more function arguments.
From cppreference. I adapted the brief to use exactly this expression function parameter pack
. Would that be clearer? At least it follows the definition more closely?
*/ | ||
template <typename unary_function_t, typename ...pack_t> | ||
//!\cond | ||
requires (std::invocable<unary_function_t, pack_t> && ... && true) |
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.
isn't this sufficient:
requires (std::invocable<unary_function_t, pack_t> && ... && true) | |
requires (std::invocable<unary_function_t, pack_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.
But it results in the exactly same result. But of course this can be expressed so as well.
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.
um yes, thats why I was wandering about the unneccessary && true
, does it have any purpose then?
a6b3f61
to
225023f
Compare
Failing build is unrelated. |
Allows to reduce a type pack or type list by checking a predicate on the type identiry of each type.