/// @cond undocumented
+#if __cplusplus >= 201103L
+ template<typename _ValueType, typename _Tp>
+ constexpr bool
+ __check_constructible()
+ {
+ // Trivial types can have deleted constructors, but std::copy etc.
+ // only use assignment (or memmove) not construction, so we need an
+ // explicit check that construction from _Tp is actually valid,
+ // otherwise some ill-formed uses of std::uninitialized_xxx would
+ // compile without errors. This gives a nice clear error message.
+ static_assert(is_constructible<_ValueType, _Tp>::value,
+ "result type must be constructible from input type");
+
+ return true;
+ }
+
+// If the type is trivial we don't need to construct it, just assign to it.
+// But trivial types can still have deleted or inaccessible assignment,
+// so don't try to use std::copy or std::fill etc. if we can't assign.
+# define _GLIBCXX_USE_ASSIGN_FOR_INIT(T, U) \
+ __is_trivial(T) && __is_assignable(T&, U) \
+ && std::__check_constructible<T, U>()
+#else
+// No need to check if is_constructible<T, U> for C++98. Trivial types have
+// no user-declared constructors, so if the assignment is valid, construction
+// should be too.
+# define _GLIBCXX_USE_ASSIGN_FOR_INIT(T, U) \
+ __is_trivial(T) && __is_assignable(T&, U)
+#endif
+
template<bool _TrivialValueTypes>
struct __uninitialized_copy
{
_ValueType1;
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType2;
+
+ // _ValueType1 must be trivially-copyable to use memmove, so don't
+ // both optimizing to std::copy if it isn't.
+ // XXX Unnecessary because std::copy would check it anyway?
+ const bool __can_memmove = __is_trivial(_ValueType1);
+
#if __cplusplus < 201103L
- const bool __assignable = true;
+ typedef typename iterator_traits<_InputIterator>::reference _From;
#else
- // Trivial types can have deleted copy constructor, but the std::copy
- // optimization that uses memmove would happily "copy" them anyway.
- static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
- "result type must be constructible from value type of input range");
-
- typedef typename iterator_traits<_InputIterator>::reference _RefType1;
- typedef typename iterator_traits<_ForwardIterator>::reference _RefType2;
- // Trivial types can have deleted assignment, so using std::copy
- // would be ill-formed. Require assignability before using std::copy:
- const bool __assignable = is_assignable<_RefType2, _RefType1>::value;
+ using _From = decltype(*__first);
#endif
+ const bool __assignable
+ = _GLIBCXX_USE_ASSIGN_FOR_INIT(_ValueType2, _From);
- return std::__uninitialized_copy<__is_trivial(_ValueType1)
- && __is_trivial(_ValueType2)
- && __assignable>::
+ return std::__uninitialized_copy<__can_memmove && __assignable>::
__uninit_copy(__first, __last, __result);
}
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType;
-#if __cplusplus < 201103L
- const bool __assignable = true;
-#else
- // Trivial types can have deleted copy constructor, but the std::fill
- // optimization that uses memmove would happily "copy" them anyway.
- static_assert(is_constructible<_ValueType, const _Tp&>::value,
- "result type must be constructible from input type");
- // Trivial types can have deleted assignment, so using std::fill
- // would be ill-formed. Require assignability before using std::fill:
- const bool __assignable = is_copy_assignable<_ValueType>::value;
-#endif
+ // Trivial types do not need a constructor to begin their lifetime,
+ // so try to use std::fill to benefit from its memset optimization.
+ const bool __can_fill
+ = _GLIBCXX_USE_ASSIGN_FOR_INIT(_ValueType, const _Tp&);
- std::__uninitialized_fill<__is_trivial(_ValueType) && __assignable>::
+ std::__uninitialized_fill<__can_fill>::
__uninit_fill(__first, __last, __x);
}
_ValueType;
// Trivial types do not need a constructor to begin their lifetime,
- // so try to use std::fill_n to benefit from its memmove optimization.
+ // so try to use std::fill_n to benefit from its optimizations.
+ const bool __can_fill
+ = _GLIBCXX_USE_ASSIGN_FOR_INIT(_ValueType, const _Tp&)
// For arbitrary class types and floating point types we can't assume
// that __n > 0 and std::__size_to_integer(__n) > 0 are equivalent,
// so only use std::fill_n when _Size is already an integral type.
-#if __cplusplus < 201103L
- const bool __can_fill = __is_integer<_Size>::__value;
-#else
- // Trivial types can have deleted copy constructor, but the std::fill_n
- // optimization that uses memmove would happily "copy" them anyway.
- static_assert(is_constructible<_ValueType, const _Tp&>::value,
- "result type must be constructible from input type");
+ && __is_integer<_Size>::__value;
- // Trivial types can have deleted assignment, so using std::fill_n
- // would be ill-formed. Require assignability before using std::fill_n:
- constexpr bool __can_fill
- = __and_<is_integral<_Size>, is_copy_assignable<_ValueType>>::value;
-#endif
- return __uninitialized_fill_n<__is_trivial(_ValueType) && __can_fill>::
+ return __uninitialized_fill_n<__can_fill>::
__uninit_fill_n(__first, __n, __x);
}
+#undef _GLIBCXX_USE_ASSIGN_FOR_INIT
+
/// @cond undocumented
// Extensions: versions of uninitialized_copy, uninitialized_fill,
* @param __n The number of elements to copy.
* @param __result An output iterator.
* @return __result + __n
+ * @since C++11
*
* Like copy_n(), but does not require an initialized output range.
*/
* @brief Default-initializes objects in the range [first,last).
* @param __first A forward iterator.
* @param __last A forward iterator.
+ * @since C++17
*/
template <typename _ForwardIterator>
inline void
* @param __first A forward iterator.
* @param __count The number of objects to construct.
* @return __first + __count
+ * @since C++17
*/
template <typename _ForwardIterator, typename _Size>
inline _ForwardIterator
* @brief Value-initializes objects in the range [first,last).
* @param __first A forward iterator.
* @param __last A forward iterator.
+ * @since C++17
*/
template <typename _ForwardIterator>
inline void
* @param __first A forward iterator.
* @param __count The number of objects to construct.
* @return __result + __count
+ * @since C++17
*/
template <typename _ForwardIterator, typename _Size>
inline _ForwardIterator
* @param __last An input iterator.
* @param __result An output iterator.
* @return __result + (__first - __last)
+ * @since C++17
*/
template <typename _InputIterator, typename _ForwardIterator>
inline _ForwardIterator
* @param __count The number of objects to initialize.
* @param __result An output iterator.
* @return __result + __count
+ * @since C++17
*/
template <typename _InputIterator, typename _Size, typename _ForwardIterator>
inline pair<_InputIterator, _ForwardIterator>
+++ /dev/null
-// Copyright (C) 2019-2021 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library. This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License along
-// with this library; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-// { dg-do compile { target c++17 } }
-
-#include <vector>
-
-// PR libstdc++/89164
-
-struct X
-{
- X() = default;
- X(const X&) = delete;
-};
-
-void test01()
-{
- X x[1];
- // Should not be able to create vector using uninitialized_copy:
- std::vector<X> v1{x, x+1}; // { dg-error "here" }
-
- // Should not be able to create vector using uninitialized_fill_n:
- std::vector<X> v2{2u, X{}}; // { dg-error "here" }
-}
-
-void test02()
-{
-#if __cplusplus >= 201703L
- // Can create initializer_list<X> with C++17 guaranteed copy elision,
- // but shouldn't be able to copy from it with uninitialized_copy:
- std::vector<X> v3{X{}, X{}, X{}}; // { dg-error "here" }
-#endif
-}
-// { dg-error "constructible from value" "" { target *-*-* } 0 }
-// { dg-error "constructible from input" "" { target *-*-* } 0 }