This is an archive of the discontinued LLVM Phabricator instance.

vector (iterator,iterator) constructor doesn't deduce second arg
AbandonedPublic

Authored by ldionne on Oct 2 2020, 4:20 AM.

Details

Reviewers
mclow.lists
miscco
kamleshbhalui
Group Reviewers
Restricted Project
Summary

since compiler can not deduce second parameter from first parameter.
when invoked as

std::vector<int> v({}, std::istream_iterator<int>{});

As part of the fix made the second parameter of vector(iterator, iterator) constructor independent of the first parameter.
fixing:
https://bugs.llvm.org/show_bug.cgi?id=47497

Diff Detail

Event Timeline

kamleshbhalui created this revision.Oct 2 2020, 4:20 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 2 2020, 4:20 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
Herald added a subscriber: dexonsmith. · View Herald Transcript
kamleshbhalui requested review of this revision.Oct 2 2020, 4:20 AM
kamleshbhalui edited the summary of this revision. (Show Details)
miscco requested changes to this revision.Oct 2 2020, 5:07 AM
miscco added a subscriber: miscco.

So the actual problem in the bug report is that the first argument cannot be used to deduce the type.

I think it is not correct to remove the type restrictions here, they are there for a reason.

That said is there any reason the constraint is placed where it is and not in the template header where I would have expected it?

This revision now requires changes to proceed.Oct 2 2020, 5:07 AM
kamleshbhalui added a comment.EditedOct 2 2020, 6:13 AM

So the actual problem in the bug report is that the first argument cannot be used to deduce the type.

I think it is not correct to remove the type restrictions here, they are there for a reason.

The only restriction is that type should be input iterator and that is still in force.

That said is there any reason the constraint is placed where it is and not in the template header where I would have expected it?

That is because the declaration and definition are at different places. And even overload with forward iterator and input iterator will collide(meaning both declarations become same).

mclow.lists requested changes to this revision.Oct 2 2020, 6:56 AM
mclow.lists added inline comments.
libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp
97

You should test both combinations.

test<std::vector<int> >(input_iterator<const int*>{}, {});
test<std::vector<int> >(forward_iterator<const int*>{}, {});

Added test suggested by @mclow.lists .

Is this a problem unique to vector? Do the other containers have the same constructor? Do those constructors have the same issue?
Checking ... list does not seem to have this problem. deque does not either. forward_list does not either.

<deque> has the following code:

template <class _InputIter>
    deque(_InputIter __f, _InputIter __l,
          typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type* = 0);
template <class _InputIter>
    deque(_InputIter __f, _InputIter __l, const allocator_type& __a,
          typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type* = 0);

I don't think that making vector different from the other containers is the right approach. Then again, I'm not 100% sure why the existing code is failing - so I should look at that.

kamleshbhalui added a comment.EditedOct 14 2020, 9:10 AM

Is this a problem unique to vector? Do the other containers have the same constructor? Do those constructors have the same issue?
Checking ... list does not seem to have this problem. deque does not either. forward_list does not either.

<deque> has the following code:

template <class _InputIter>
    deque(_InputIter __f, _InputIter __l,
          typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type* = 0);
template <class _InputIter>
    deque(_InputIter __f, _InputIter __l, const allocator_type& __a,
          typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type* = 0);

I don't think that making vector different from the other containers is the right approach. Then again, I'm not 100% sure why the existing code is failing - so I should look at tha

Looks like because of this patch vector deviated from other container implementation.
http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20130916/089030.html

mclow.lists added a comment.EditedOct 14 2020, 9:14 AM

Looks like because of this patch vector deviated from other container implementation.
http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20130916/089030.html

and if you look at https://reviews.llvm.org/D1723, Richard Smith pointed out this exact issue ... in 2013. :-(

So the goals of this patch should be:

  • Resolve the original problem,
  • Decide if the problem shown in D1723 is real, and if so, make sure that still works, and
  • Make all the containers do resolve this the same way.
  • Make all the containers do resolve this the same way.

While preserving vectors optimization for forward iterators, of course.

It should be possible to use the following pattern instead, I think:

template <class _InputIterator, class = enable-if-expression>
vector(_InputIterator __first, _InputIterator __last);

This may not work in C++03 mode where default template arguments are not allowed IIRC, but maybe we can have a C++03 specific workaround?

ldionne commandeered this revision.Sep 8 2023, 11:15 AM
ldionne edited reviewers, added: kamleshbhalui; removed: ldionne.

Per the update in https://github.com/llvm/llvm-project/issues/46841, it seems like this was fixed somewhere between Clang 15 and Clang 16.

I'll drop this to clear our queue as part of the Github PR transition.

Herald added a project: Restricted Project. · View Herald TranscriptSep 8 2023, 11:15 AM
Herald added a subscriber: sunshaoce. · View Herald Transcript
ldionne abandoned this revision.Sep 8 2023, 11:16 AM