[PATCH] [libc++] Move enable_if to 2nd argument of std::vector(iterator, iterator) ctor
Howard Hinnant
howard.hinnant at gmail.com
Sat Sep 21 14:18:27 PDT 2013
Nice. Committed revision 191145.
In the future please also test with:
$ export OPTIONS="-std=c++03 -stdlib=libc++"
I think there are many places like this that could use the same treatment.
Howard
On Sep 19, 2013, at 12:59 AM, Peter Collingbourne <peter at pcc.me.uk> wrote:
> If a pointer is passed as the third argument of the (iterator,
> iterator, allocator) constructor with the intention of it being
> implicitly converted to the allocator type, it is possible for overload
> resolution to favour the (iterator, iterator, enable_if) constructor.
> Eliminate this possibility by moving the enable_if to one of the
> existing arguments and removing the third argument.
>
> http://llvm-reviews.chandlerc.com/D1723
>
> Files:
> include/vector
> test/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp
>
> Index: include/vector
> ===================================================================
> --- include/vector
> +++ include/vector
> @@ -519,25 +519,27 @@
> vector(size_type __n, const_reference __x);
> vector(size_type __n, const_reference __x, const allocator_type& __a);
> template <class _InputIterator>
> - vector(_InputIterator __first, _InputIterator __last,
> + vector(_InputIterator __first,
> typename enable_if<__is_input_iterator <_InputIterator>::value &&
> !__is_forward_iterator<_InputIterator>::value &&
> is_constructible<
> value_type,
> - typename iterator_traits<_InputIterator>::reference>::value>::type* = 0);
> + typename iterator_traits<_InputIterator>::reference>::value,
> + _InputIterator>::type __last);
> template <class _InputIterator>
> vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a,
> typename enable_if<__is_input_iterator <_InputIterator>::value &&
> !__is_forward_iterator<_InputIterator>::value &&
> is_constructible<
> value_type,
> typename iterator_traits<_InputIterator>::reference>::value>::type* = 0);
> template <class _ForwardIterator>
> - vector(_ForwardIterator __first, _ForwardIterator __last,
> + vector(_ForwardIterator __first,
> typename enable_if<__is_forward_iterator<_ForwardIterator>::value &&
> is_constructible<
> value_type,
> - typename iterator_traits<_ForwardIterator>::reference>::value>::type* = 0);
> + typename iterator_traits<_ForwardIterator>::reference>::value,
> + _ForwardIterator>::type __last);
> template <class _ForwardIterator>
> vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a,
> typename enable_if<__is_forward_iterator<_ForwardIterator>::value &&
> @@ -1051,12 +1053,13 @@
>
> template <class _Tp, class _Allocator>
> template <class _InputIterator>
> -vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last,
> +vector<_Tp, _Allocator>::vector(_InputIterator __first,
> typename enable_if<__is_input_iterator <_InputIterator>::value &&
> !__is_forward_iterator<_InputIterator>::value &&
> is_constructible<
> value_type,
> - typename iterator_traits<_InputIterator>::reference>::value>::type*)
> + typename iterator_traits<_InputIterator>::reference>::value,
> + _InputIterator>::type __last)
> {
> #if _LIBCPP_DEBUG_LEVEL >= 2
> __get_db()->__insert_c(this);
> @@ -1084,11 +1087,12 @@
>
> template <class _Tp, class _Allocator>
> template <class _ForwardIterator>
> -vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last,
> +vector<_Tp, _Allocator>::vector(_ForwardIterator __first,
> typename enable_if<__is_forward_iterator<_ForwardIterator>::value &&
> is_constructible<
> value_type,
> - typename iterator_traits<_ForwardIterator>::reference>::value>::type*)
> + typename iterator_traits<_ForwardIterator>::reference>::value,
> + _ForwardIterator>::type __last)
> {
> #if _LIBCPP_DEBUG_LEVEL >= 2
> __get_db()->__insert_c(this);
> Index: test/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp
> ===================================================================
> --- test/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp
> +++ test/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp
> @@ -19,17 +19,24 @@
> #include "../../../stack_allocator.h"
> #include "../../../min_allocator.h"
>
> -template <class C, class Iterator>
> +template <class C, class Iterator, class A>
> void
> -test(Iterator first, Iterator last, const typename C::allocator_type& a)
> +test(Iterator first, Iterator last, const A& a)
> {
> C c(first, last, a);
> assert(c.__invariants());
> assert(c.size() == std::distance(first, last));
> for (typename C::const_iterator i = c.cbegin(), e = c.cend(); i != e; ++i, ++first)
> assert(*i == *first);
> }
>
> +template <class T>
> +struct implicit_conv_allocator : min_allocator<T>
> +{
> + implicit_conv_allocator(void* p) {}
> + implicit_conv_allocator(const implicit_conv_allocator&) = default;
> +};
> +
> int main()
> {
> {
> @@ -52,6 +59,7 @@
> test<std::vector<int, min_allocator<int>> >(bidirectional_iterator<const int*>(a), bidirectional_iterator<const int*>(an), alloc);
> test<std::vector<int, min_allocator<int>> >(random_access_iterator<const int*>(a), random_access_iterator<const int*>(an), alloc);
> test<std::vector<int, min_allocator<int>> >(a, an, alloc);
> + test<std::vector<int, implicit_conv_allocator<int>> >(a, an, nullptr);
> }
> #endif
> }
> <D1723.1.patch>_______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list