vsapsai created this revision. vsapsai added reviewers: mclow.lists, EricWF. Herald added a subscriber: christof.
We already have a specialization that will use memcpy for construction of trivial types from an iterator range like std::vector<int>(int *, int *); But if we have const-ness mismatch like std::vector<int>(const int *, const int *); we would use a slow path that copies each element individually. This change enables the optimal specialization for const-ness mismatch. Fixes PR37574. rdar://problem/40485845 https://reviews.llvm.org/D48342 Files: libcxx/include/memory libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_different_value_type.pass.cpp
Index: libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_different_value_type.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_different_value_type.pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <vector> + +// template <class InputIter> vector(InputIter first, InputIter last); + +// Initialize a vector with a different value type. Make sure initialization +// is performed with each element value, not with a memory blob. + +#include <vector> +#include <cassert> +#include <cfloat> +#include <cmath> + +int main() +{ + int array[3] = {0, 1, 2}; + std::vector<float> v(array, array + 3); + assert(std::fabs(v[0] - 0.0f) < FLT_EPSILON); + assert(std::fabs(v[1] - 1.0f) < FLT_EPSILON); + assert(std::fabs(v[2] - 2.0f) < FLT_EPSILON); +} Index: libcxx/include/memory =================================================================== --- libcxx/include/memory +++ libcxx/include/memory @@ -1399,6 +1399,13 @@ { }; +template <class _Alloc, class _Pointer, class ..._Args> +struct __has_construct_missing + : integral_constant<bool, + !__has_construct<_Alloc, _Pointer, _Args...>::value> +{ +}; + template <class _Alloc, class _Pointer> auto __has_destroy_test(_Alloc&& __a, _Pointer&& __p) @@ -1467,14 +1474,26 @@ { }; +template <class _Alloc, class _Pointer, class ..._Args> +struct __has_construct_missing + : false_type +{ +}; + #else // _LIBCPP_HAS_NO_VARIADICS template <class _Alloc, class _Pointer, class _Args> struct __has_construct : false_type { }; +template <class _Alloc, class _Pointer, class _Args> +struct __has_construct_missing + : false_type +{ +}; + #endif // _LIBCPP_HAS_NO_VARIADICS template <class _Alloc, class _Pointer> @@ -1622,7 +1641,7 @@ typename enable_if < (is_same<allocator_type, allocator<_Tp> >::value - || !__has_construct<allocator_type, _Tp*, _Tp>::value) && + || __has_construct_missing<allocator_type, _Tp*, _Tp>::value) && is_trivially_move_constructible<_Tp>::value, void >::type @@ -1646,23 +1665,27 @@ construct(__a, _VSTD::__to_raw_pointer(__begin2), *__begin1); } - template <class _Tp> + template <class _SourceTp, class _DestTp> _LIBCPP_INLINE_VISIBILITY static typename enable_if < - (is_same<allocator_type, allocator<_Tp> >::value - || !__has_construct<allocator_type, _Tp*, _Tp>::value) && - is_trivially_move_constructible<_Tp>::value, + (is_same + < + typename _VSTD::remove_const<typename allocator_type::value_type>::type, + typename _VSTD::remove_const<_SourceTp>::type + >::value + || __has_construct_missing<allocator_type, _DestTp*, _SourceTp>::value) && + is_trivially_move_constructible<_DestTp>::value, void >::type - __construct_range_forward(allocator_type&, _Tp* __begin1, _Tp* __end1, _Tp*& __begin2) + __construct_range_forward(allocator_type&, _SourceTp* __begin1, _SourceTp* __end1, _DestTp*& __begin2) { - typedef typename remove_const<_Tp>::type _Vp; + typedef typename remove_const<_DestTp>::type _Vp; ptrdiff_t _Np = __end1 - __begin1; if (_Np > 0) { - _VSTD::memcpy(const_cast<_Vp*>(__begin2), __begin1, _Np * sizeof(_Tp)); + _VSTD::memcpy(const_cast<_Vp*>(__begin2), __begin1, _Np * sizeof(_DestTp)); __begin2 += _Np; } } @@ -1686,7 +1709,7 @@ typename enable_if < (is_same<allocator_type, allocator<_Tp> >::value - || !__has_construct<allocator_type, _Tp*, _Tp>::value) && + || __has_construct_missing<allocator_type, _Tp*, _Tp>::value) && is_trivially_move_constructible<_Tp>::value, void >::type
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits