Make array<const T, 0> non-CopyAssignable and make swap and fill ill-formed.
The standard isn't exactly clear how std::array should handle zero-sized arrays
with const element types. In particular W.R.T. copy assignment, swap, and fill.
This patch takes the position that those operations should be ill-formed,
and makes changes to libc++ to make it so.
This follows up on commit r324182.
llvm-svn: 324185
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 192622dc49d3f7fe31d6512d0e85fd03fbb39a62
diff --git a/include/array b/include/array
index 8cd3ecd..4a89ea9 100644
--- a/include/array
+++ b/include/array
@@ -122,7 +122,8 @@
typedef _Tp _StorageT[_Size];
_LIBCPP_INLINE_VISIBILITY
- static _LIBCPP_CONSTEXPR_AFTER_CXX14 _Tp* __data(_StorageT& __store) {
+ static _LIBCPP_CONSTEXPR_AFTER_CXX14 typename remove_const<_Tp>::type*
+ __data(typename remove_const<_StorageT>::type& __store) {
return __store;
}
@@ -144,12 +145,16 @@
template <class _Tp>
struct __array_traits<_Tp, 0> {
- typedef typename aligned_storage<sizeof(_Tp), alignment_of<_Tp>::value>::type _StorageT;
+ typedef typename aligned_storage<sizeof(_Tp), alignment_of<_Tp>::value>::type
+ _NonConstStorageT;
+ typedef typename conditional<is_const<_Tp>::value, const _NonConstStorageT,
+ _NonConstStorageT>::type _StorageT;
+ typedef typename remove_const<_Tp>::type _NonConstTp;
_LIBCPP_INLINE_VISIBILITY
- static _Tp* __data(_StorageT& __store) {
+ static _NonConstTp* __data(_NonConstStorageT& __store) {
_StorageT *__ptr = std::addressof(__store);
- return reinterpret_cast<_Tp*>(__ptr);
+ return reinterpret_cast<_NonConstTp*>(__ptr);
}
_LIBCPP_INLINE_VISIBILITY
@@ -162,8 +167,7 @@
static void __swap(_StorageT&, _StorageT&) {}
_LIBCPP_INLINE_VISIBILITY
- static void __fill(_StorageT&, _Tp const&) {
- }
+ static void __fill(_StorageT&, _Tp const&) {}
};
template <class _Tp, size_t _Size>
@@ -187,12 +191,19 @@
typename _Traits::_StorageT __elems_;
// No explicit construct/copy/destroy for aggregate type
- _LIBCPP_INLINE_VISIBILITY void fill(const value_type& __u)
- {_Traits::__fill(__elems_, __u);}
+ _LIBCPP_INLINE_VISIBILITY void fill(const value_type& __u) {
+ static_assert(_Size != 0 || !is_const<_Tp>::value,
+ "cannot fill zero-sized array of type 'const T'");
+ _Traits::__fill(__elems_, __u);
+ }
_LIBCPP_INLINE_VISIBILITY
- void swap(array& __a) _NOEXCEPT_(_Size == 0 || __is_nothrow_swappable<_Tp>::value)
- { _Traits::__swap(__elems_, __a.__elems_); }
+ void swap(array& __a)
+ _NOEXCEPT_(_Size == 0 || __is_nothrow_swappable<_Tp>::value) {
+ static_assert(_Size != 0 || !is_const<_Tp>::value,
+ "cannot swap zero-sized array of type 'const T'");
+ _Traits::__swap(__elems_, __a.__elems_);
+ }
// iterators:
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14