Using the enable_if_t<..., int> = 0 style has the benefit that it works in all cases and makes function declarations easier to read because the function arguments and return type and SFINAE are separated. Unifying the style also makes it easier for people not super familiar with SFINAE to make sense of the code.
Details
- Reviewers
ldionne Mordante var-const huixie90 - Group Reviewers
Restricted Project - Commits
- rG54150e8257e4: [libc++][NFC] Refactor enable_ifs in vector
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
LGTM with comments addressed. lots of enable_ifs are checking the cpp 17 forward iterator. I wonder if we can relax it to cpp 20 forward iterator. (cpp 17 forward iterator requires reference being a reference type, which is not important for these vector members IIUC)
libcxx/include/vector | ||
---|---|---|
1000 | Technically the enable_if still applies since the default template argument with enable_if already exists in the function declaration few hundred lines above. But I agree it is not obvious since the declaration and definition are few hundred lines apart from each other. Also I agree that using non-type template is better because it is consistent with others, although technically it is not required to use non-type template parameter since there is only one overload |
LGTM!
libcxx/include/vector | ||
---|---|---|
1000 |
Thanks I missed that in the original review. |
Can you please add the rationale for this change to the patch description? Other than that and the couple optional comments, LGTM.
libcxx/include/vector | ||
---|---|---|
395–396 | It looks like there are 2 same conditions repeated throughout the file: __is_exactly_cpp17_input_iterator<_InputIterator>::value && is_constructible<value_type, typename iterator_traits<_InputIterator>::reference> and __is_cpp17_forward_iterator<_ForwardIterator>::value && is_constructible<value_type, typename iterator_traits<_ForwardIterator>::reference> Perhaps create helper traits for those, e.g. IsConstructibleFromInputIterator/IsConstuctibleFromForwardIterator? It should help cut down on the boilerplate, particularly when repeating the enable_if in the function definition. If you decide to do this, it's likely best to do in a follow-up. | |
1088 | Nit: it's unfortunate that now some of the conditions use _Tp and others value_type, just from the consistency perspective. I presume it's not possible to use value_type here because it's not in scope yet at this point. Would it make sense to go the other way round and use _Tp in other places instead of value_type? |
I am 90% certain that this caused the following change of behavior: https://godbolt.org/z/WKEadqf8e. Long story short, constructing a vector with iterators with a mismatched constness used to work, and now it doesn't anymore. GCC doesn't support it either.
@philnik Since this is almost certainly unintended, can you please figure out what the valid standard behavior is here and add a test if the standard mandates that?
Also, I noticed because it broke some code. It did not result in any significant breakage, but if the new behavior is the correct one and we keep it, we should add a release note just as a heads up.
It looks like there are 2 same conditions repeated throughout the file:
and
Perhaps create helper traits for those, e.g. IsConstructibleFromInputIterator/IsConstuctibleFromForwardIterator? It should help cut down on the boilerplate, particularly when repeating the enable_if in the function definition. If you decide to do this, it's likely best to do in a follow-up.