for (; __first != __last; ++__first)
std::_Destroy(std::__addressof(*__first));
}
+
+ template<typename _ForwardIterator, typename _Size>
+ static _GLIBCXX20_CONSTEXPR _ForwardIterator
+ __destroy_n(_ForwardIterator __first, _Size __count)
+ {
+ for (; __count > 0; (void)++__first, --__count)
+ std::_Destroy(std::__addressof(*__first));
+ return __first;
+ }
};
template<>
template<typename _ForwardIterator>
static void
__destroy(_ForwardIterator, _ForwardIterator) { }
+
+ template<typename _ForwardIterator, typename _Size>
+ static _ForwardIterator
+ __destroy_n(_ForwardIterator __first, _Size __count)
+ {
+ std::advance(__first, __count);
+ return __first;
+ }
};
#endif
typedef typename iterator_traits<_ForwardIterator>::value_type
_Value_type;
#if __cplusplus >= 201103L
- // A deleted destructor is trivial, this ensures we reject such types:
- static_assert(is_destructible<_Value_type>::value,
- "value type is destructible");
- if constexpr (!__has_trivial_destructor(_Value_type))
+ if constexpr (!is_trivially_destructible<_Value_type>::value)
for (; __first != __last; ++__first)
std::_Destroy(std::__addressof(*__first));
#if __cpp_constexpr_dynamic_alloc // >= C++20
#endif
}
-#if __cplusplus < 201103L
- template<bool>
- struct _Destroy_n_aux
- {
- template<typename _ForwardIterator, typename _Size>
- static _GLIBCXX20_CONSTEXPR _ForwardIterator
- __destroy_n(_ForwardIterator __first, _Size __count)
- {
- for (; __count > 0; (void)++__first, --__count)
- std::_Destroy(std::__addressof(*__first));
- return __first;
- }
- };
-
- template<>
- struct _Destroy_n_aux<true>
- {
- template<typename _ForwardIterator, typename _Size>
- static _ForwardIterator
- __destroy_n(_ForwardIterator __first, _Size __count)
- {
- std::advance(__first, __count);
- return __first;
- }
- };
-#endif
-
/**
* Destroy a range of objects. If the value_type of the object has
* a trivial destructor, the compiler should optimize all of this
typedef typename iterator_traits<_ForwardIterator>::value_type
_Value_type;
#if __cplusplus >= 201103L
- // A deleted destructor is trivial, this ensures we reject such types:
- static_assert(is_destructible<_Value_type>::value,
- "value type is destructible");
- if constexpr (!__has_trivial_destructor(_Value_type))
+ if constexpr (!is_trivially_destructible<_Value_type>::value)
for (; __count > 0; (void)++__first, --__count)
std::_Destroy(std::__addressof(*__first));
#if __cpp_constexpr_dynamic_alloc // >= C++20
std::advance(__first, __count);
return __first;
#else
- return std::_Destroy_n_aux<__has_trivial_destructor(_Value_type)>::
+ return std::_Destroy_aux<__has_trivial_destructor(_Value_type)>::
__destroy_n(__first, __count);
#endif
}
--- /dev/null
+// Copyright (C) 2017-2025 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 <memory>
+
+// This has a trivial destructor, but should not be destructible!
+struct DeletedDtor {
+ ~DeletedDtor() = delete;
+};
+
+void
+test01()
+{
+ alignas(DeletedDtor) unsigned char buf[sizeof(DeletedDtor)];
+ auto p = ::new (buf) DeletedDtor();
+ std::destroy_n(p, 1);
+}
+
+class PrivateDtor {
+ ~PrivateDtor() { }
+};
+
+void
+test02()
+{
+ alignas(PrivateDtor) unsigned char buf[sizeof(PrivateDtor)];
+ auto p = ::new (buf) PrivateDtor();
+ std::destroy_n(p, 1);
+}
+
+#if __cpp_constexpr_dynamic_alloc // >= C++20
+consteval bool
+test03()
+{
+ DeletedDtor* p = nullptr;
+ std::destroy_n(p, 0);
+ return true;
+}
+static_assert(test03());
+#endif
+
+// { dg-error "deleted function .*DeletedDtor" "" { target *-*-* } 0 }
+// { dg-error "PrivateDtor.* is private" "" { target *-*-* } 0 }
{
alignas(DeletedDtor) unsigned char buf[sizeof(DeletedDtor)];
auto p = ::new (buf) DeletedDtor();
- std::destroy(p, p + 1); // { dg-error "here" }
- std::destroy_n(p, 1); // { dg-error "here" }
+ std::destroy(p, p + 1);
}
class PrivateDtor {
{
alignas(PrivateDtor) unsigned char buf[sizeof(PrivateDtor)];
auto p = ::new (buf) PrivateDtor();
- std::destroy(p, p + 1); // { dg-error "here" }
- std::destroy_n(p, 1); // { dg-error "here" }
+ std::destroy(p, p + 1);
}
-// { dg-error "value type is destructible" "" { target *-*-* } 0 }
+#if __cpp_constexpr_dynamic_alloc // >= C++20
+consteval bool
+test03()
+{
+ DeletedDtor* p = nullptr;
+ std::destroy(p, p);
+ return true;
+}
+static_assert(test03());
+#endif
+
+// { dg-error "deleted function .*DeletedDtor" "" { target *-*-* } 0 }
+// { dg-error "PrivateDtor.* is private" "" { target *-*-* } 0 }