-
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] our own meta library #1204
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1204 +/- ##
=======================================
Coverage 96.72% 96.72%
=======================================
Files 210 210
Lines 8003 8003
=======================================
Hits 7741 7741
Misses 262 262 Continue to review full report at Codecov.
|
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.
Looks quite nice. In general if you switch this to another header we might as well get the for_each... functions in core/algorithm/parameter_pack.hpp
to the proper headers and namespaces. That would also mean some API breakage so you need to add a Changelog entry as well.
@@ -19,6 +19,10 @@ | |||
namespace seqan3 | |||
{ | |||
|
|||
// ---------------------------------------------------------------------------- | |||
// type_list class | |||
// ---------------------------------------------------------------------------- |
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.
we do need a followup issue to remove all meta::
dependencies and replace them with our own. Can you track this somewhere explicit?
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 know.
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.
added a card to Core project
include/seqan3/core/type_list.hpp
Outdated
* \ingroup type_traits | ||
*/ | ||
template <ptrdiff_t idx, typename head_t, typename ...tail_t> | ||
auto at_impl() |
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, since it is in detail we might not need the impl suffix right?
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.
well they are different things (type vs functions...) so I wasn't sure. But I don't care much about it.
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 all impl stuff are now functions, aren't they?
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, but the public entity isn't. Anyway, I can change it.
include/seqan3/core/type_list.hpp
Outdated
* Constant. | ||
*/ | ||
template <typename ...pack_t> | ||
using concat = type_list<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.
that is confusing to me since I expect something different from a concat. Also I know what you mean but you are not concatenating two or more packs. From STL nomenclature this would be more a make_type_list
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.
Honestly, I don't think we need this at all. I mean that would be simply type_list<t1, t2, t3, t4>
. Why bother to have a separate traits for this, which is basically just an alias?
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.
Well I wanted to keep the interfaces for list VS types very similar.
You might have
template <typename list1, typename list2>
and want to go to concat<list1, list2>
.
Similarly:
template <typename ...pack1, typename ...pack2>
and go to concat<pack1..., pack2...>
.
Of course you could just write type_list
for the packs, but I think there is value in consistency...
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, there is no consistency with this, because
template <typename ...pack1, typename ...pack2>
won't be possible if they are not already wrapped in some class. Which does not happen to often outside of the context of type_lists anyway. Also since they are in different namespaces you have to explicitly choose the traits anyway. Hence, there is no need for consistency. Either I am in the context of parameter packs or I am in the context of type_lists. Because then you could also argue that you could allow
template <typename ...pack1, typename ...pack2, typename ...pack3>
...
concat<pack1..., pack2..., pack3....>
But this does not work with type_lists and would be more confusing then because of inconsistencies. Of course we could blow up the concat for type_lists but I think that it is rarely necessary (ok, let's see about that). So I'd like to keep these things separate and would argue that for parameter packs a concat is simply not necessary.
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 convinced fully, but I will remove, because it's really not that important.
include/seqan3/core/type_list.hpp
Outdated
seqan3::pack_traits::drop_front<pack_t...> drop_front_impl(type_list<pack_t...>); | ||
|
||
/*!\brief Implementation for take, drop, take_last and drop_last in seqan3::list_traits. | ||
* \tparam idx The after which to split. |
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.
* \tparam idx The after which to split. | |
* \tparam idx The index after which to split. |
include/seqan3/core/type_list.hpp
Outdated
* \ingroup type_traits | ||
*/ | ||
template <ptrdiff_t idx, typename ...pack_t> | ||
std::type_identity<seqan3::pack_traits::at<idx, pack_t...>> at_impl(type_list<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.
same here the impl in the name is kind of redundant given that is is in detail already
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 can change it if you want to.
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, because otherwise it would deviate from the rest of the code base and kind of counteracts the meaning of the detail namespace.
include/seqan3/core/type_list.hpp
Outdated
//!\cond | ||
requires (n >= 0 && n <= size<list_t>) | ||
//!\endcond | ||
using drop_last = typename decltype(detail::split_after_impl<size<list_t> - n>(type_list<>{}, list_t{}))::first_type; |
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.
accordingly we can model this with the negative index and with take as well. I think it is more readable.
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 had it like that before, but it's horrible 👻
The problem is that it gets very confusing regarding inclusive/exclusive indexing.
take and drop are specifically not modeled as "take until third element", but as "take three elements". What would take<-3>
imply? "Take until the third-last"? Before or after? What does it imply regarding the size of the list?
This way it is very simple: take<n>
and take_last <n>
always return something of size n. drop<n>
and drop_last <n>
always return something of the original size - n.
range-v3 is also getting a view::take_last
so we would be in-sync regarding naming.
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.
Well, the negative index would perfectly align with take because take<-3> takes exactly the last three elements. That's how it is implemented anyway (take_last<n> <=> drop<N-n>
). Thus you would have take<N> == take<-N>
and take<1> <=> at<0>
and take<-1> <=> at<N-1> <=> at<-1>
.
But if the ranges library get's a special take_last then why not having it here as well. But honestly, I don't like that at
has then a different semantics. But oh boy, at_last
would be the wrong way to go 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.
Well, the negative index would perfectly align with take because take<-3> takes exactly the last three elements.
Oh, wow, ok, you thought it would work that way.
But if the ranges library get's a special take_last then why not having it here as well.
Yes, I really think it makes it clearer as we are not working with indexes at all, but with counts. And negative counts are weird.
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.
Oh, wow, ok, you thought it would work that way.
It should work that way if at
works that way!
include/seqan3/core/type_list.hpp
Outdated
//!\cond | ||
requires (n >= 0 && n <= size<list_t>) | ||
//!\endcond | ||
using take_last = typename decltype(detail::split_after_impl<size<list_t> - n>(type_list<>{}, list_t{}))::second_type; |
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.
First of all this would be the same as:
using take_last = typename decltype(detail::split_after_impl<size<list_t> - n>(type_list<>{}, list_t{}))::second_type; | |
using take_last = drop<size<list_t> - n>; |
right?
And I am wondering if this should not be modeled with negative indicestake<-n, list_t>
?
That would it make consistent with at
So:
template <ptrdiff_t n, seqan3::detail::TypeList list_t>
//!\cond
requires (n < 0 && -n <= size<list_t>)
//!\endcond
using take = drop<size<list_t> + n>;
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 agree, it can be written shorter. See above for why I am opposed to negative idnexing there.
(Believe me, I wanted this, I designed it that way and it confused me so much I got convinced it wasn't a good idea)
test/unit/core/type_list_test.cpp
Outdated
|
||
TEST(pack_traits, size) | ||
{ | ||
EXPECT_EQ(( pack_traits::size<int, bool &, double const> ), |
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.
EXPECT_EQ(( pack_traits::size<int, bool &, double const> ), | |
EXPECT_EQ((pack_traits::size<int, bool &, double const>), |
test/unit/core/type_list_test.cpp
Outdated
|
||
TEST(pack_traits, concat) | ||
{ | ||
EXPECT_TRUE((std::is_same_v<pack_traits::concat<int, bool &, double const, long, float>, |
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 think we really don't need this. There is no added functionality by this.
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.
It's just an alias 🤷♂️
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 as I said above an alias that does allow more functionality than it's type list counterpart
I think I have adressed all of your issues. I have also moved the stuff around and added a changelog. |
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. Only some 💅 stuff
return std::type_identity<__type_pack_element<idx - 1, tail_t...>>; | ||
#else | ||
return at<idx - 1, tail_t...>(); | ||
#endif |
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.
can you mark with a comment that this is builtin ends here.
This is our own meta library with almost identical interfaces for dealing with seqan3::type_list, but also parameter packs (it's usually faster to work on the latter).
Currently available:
Notably absent:
void
to the top and the commas to the front.