diff options
| author | Eric Fiselier <eric@efcs.ca> | 2018-02-04 02:17:02 +0000 |
|---|---|---|
| committer | Eric Fiselier <eric@efcs.ca> | 2018-02-04 02:17:02 +0000 |
| commit | 192622dc49d3f7fe31d6512d0e85fd03fbb39a62 (patch) | |
| tree | 20724db2976a3a2ce0d328306e41b8bfb3a5c496 /libcxx/include/array | |
| parent | 8d511a65aff2085eba0ad5c6699fefb1f601a0b5 (diff) | |
| download | bcm5719-llvm-192622dc49d3f7fe31d6512d0e85fd03fbb39a62.tar.gz bcm5719-llvm-192622dc49d3f7fe31d6512d0e85fd03fbb39a62.zip | |
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
Diffstat (limited to 'libcxx/include/array')
| -rw-r--r-- | libcxx/include/array | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/libcxx/include/array b/libcxx/include/array index 8cd3ecdf9e7..4a89ea90d44 100644 --- a/libcxx/include/array +++ b/libcxx/include/array @@ -122,7 +122,8 @@ struct __array_traits { 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 @@ struct __array_traits { 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 @@ struct __array_traits<_Tp, 0> { 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 @@ struct _LIBCPP_TEMPLATE_VIS array 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 |

