STL:std::array 和 基本数组类型array 浅谈一二三
2023-12-26 12:32:30
一、优缺点比较
在C++中,std::array
是标准库提供的数组容器,相比于基础数据类型的数组,它具有以下优点和缺点:
优点:
-
- 安全性:
std::array
提供了边界检查,可以避免数组越界访问的问题。
- 安全性:
-
- 可以作为函数参数:
std::array
可以作为函数的参数和返回值,而基础数据类型的数组不能直接作为函数参数传递。
- 可以作为函数参数:
-
- 支持STL算法:
std::array
可以直接使用STL算法,如std::sort
、std::find
等,而基础数据类型的数组需要手动实现这些算法。
- 支持STL算法:
缺点:
-
- 大小固定:
std::array
的大小在编译时就需要确定,无法动态改变大小,而基础数据类型的数组可以使用new
和delete
动态分配和释放内存。
- 大小固定:
-
- 初始化复杂:相比于基础数据类型的数组,
std::array
的初始化语法可能更加繁琐。std::array
不支持参数列表的初始化形式。
- 初始化复杂:相比于基础数据类型的数组,
总的来说,std::array
相比于基础数据类型的数组更加安全和方便,但在某些情况下可能会有一些额外的开销和限制。
二、代码示例
#include <any>
#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <array>
#include <set>
#include <queue>
#include <deque>
#include <algorithm>
using namespace std;
#define NOUSE(x) (void)x;
// test array
template <typename _Ty,size_t N>
void array_test_func(std::array<_Ty,N>& arr)
{
/// 通过迭代器遍历
auto traver_1 = [&](){
#if 0
auto iter = arr.begin();
for(;iter != arr.end();++iter)
cout << *iter << " ";
#else
std::copy(arr.cbegin(), arr.cend(), std::ostream_iterator<_Ty>(std::cout, " "));
#endif
cout << endl;
};
traver_1();
cout << "back ==> " << arr.back() << endl; // 首字符
cout << "front ==> " << arr.front() << endl; // 尾字符
size_t n = arr.size(); // 长度
/// 通过数组指针遍历
auto traver_2 = [&](){
_Ty* dptr = arr.data(); // 首地址
for(size_t i = 0; i < n ;++i){
cout << *(dptr+i) << " ";
}
cout << endl;
};
traver_2();
/// 通过下标遍历
auto traver_3 = [&](){
for(size_t i = 0; i < n;++i){
cout << arr.at(i) << " ";
}
cout << endl;
};
traver_3();
}
int main(int argc, char *argv[])
{
NOUSE(argc);
NOUSE(argv);
std::array<int,3> arr = {2,6,4};
array_test_func<int,3>(arr);
// array_test_func<int,3>({2,4,6}); // error : 不支持 initializer_list
std::sort(arr.begin(),arr.end()); // 支持STL算法
array_test_func<int,3>(arr);
return 0;
}
三、源码赏析
// array standard header
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#pragma once
#ifndef _ARRAY_
#define _ARRAY_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#include <xutility>
#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new
_STD_BEGIN
#if _ITERATOR_DEBUG_LEVEL != 0
struct _Iterator_base12_compatible { // TRANSITION, for binary compatibility
_Container_proxy* _Myproxy{};
_Iterator_base12* _Mynextiter{};
};
#endif // _ITERATOR_DEBUG_LEVEL != 0
定于数组的const迭代器
template <class _Ty, size_t _Size>
class _Array_const_iterator
#if _ITERATOR_DEBUG_LEVEL != 0
: private _Iterator_base12_compatible
#endif // _ITERATOR_DEBUG_LEVEL != 0
{
public:
#ifdef __cpp_lib_concepts
using iterator_concept = contiguous_iterator_tag;
#endif // __cpp_lib_concepts
using iterator_category = random_access_iterator_tag;
using value_type = _Ty;
using difference_type = ptrdiff_t;
using pointer = const _Ty*;
using reference = const _Ty&;
enum { _EEN_SIZE = _Size }; // helper for expression evaluator
#if _ITERATOR_DEBUG_LEVEL == 0
_CONSTEXPR17 _Array_const_iterator() noexcept : _Ptr() {}
_CONSTEXPR17 explicit _Array_const_iterator(pointer _Parg, size_t _Off = 0) noexcept : _Ptr(_Parg + _Off) {}
_NODISCARD _CONSTEXPR17 reference operator*() const noexcept {
return *_Ptr;
}
_NODISCARD _CONSTEXPR17 pointer operator->() const noexcept {
return _Ptr;
}
_CONSTEXPR17 _Array_const_iterator& operator++() noexcept {
++_Ptr;
return *this;
}
_CONSTEXPR17 _Array_const_iterator operator++(int) noexcept {
_Array_const_iterator _Tmp = *this;
++_Ptr;
return _Tmp;
}
_CONSTEXPR17 _Array_const_iterator& operator--() noexcept {
--_Ptr;
return *this;
}
_CONSTEXPR17 _Array_const_iterator operator--(int) noexcept {
_Array_const_iterator _Tmp = *this;
--_Ptr;
return _Tmp;
}
_CONSTEXPR17 _Array_const_iterator& operator+=(const ptrdiff_t _Off) noexcept {
_Ptr += _Off;
return *this;
}
_NODISCARD _CONSTEXPR17 _Array_const_iterator operator+(const ptrdiff_t _Off) const noexcept {
_Array_const_iterator _Tmp = *this;
return _Tmp += _Off;
}
_CONSTEXPR17 _Array_const_iterator& operator-=(const ptrdiff_t _Off) noexcept {
_Ptr -= _Off;
return *this;
}
_NODISCARD _CONSTEXPR17 _Array_const_iterator operator-(const ptrdiff_t _Off) const noexcept {
_Array_const_iterator _Tmp = *this;
return _Tmp -= _Off;
}
_NODISCARD _CONSTEXPR17 ptrdiff_t operator-(const _Array_const_iterator& _Right) const noexcept {
return _Ptr - _Right._Ptr;
}
_NODISCARD _CONSTEXPR17 reference operator[](const ptrdiff_t _Off) const noexcept {
return _Ptr[_Off];
}
_NODISCARD _CONSTEXPR17 bool operator==(const _Array_const_iterator& _Right) const noexcept {
return _Ptr == _Right._Ptr;
}
#if _HAS_CXX20
_NODISCARD constexpr strong_ordering operator<=>(const _Array_const_iterator& _Right) const noexcept {
return _Ptr <=> _Right._Ptr;
}
#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv
_NODISCARD _CONSTEXPR17 bool operator!=(const _Array_const_iterator& _Right) const noexcept {
return !(*this == _Right);
}
_NODISCARD _CONSTEXPR17 bool operator<(const _Array_const_iterator& _Right) const noexcept {
return _Ptr < _Right._Ptr;
}
_NODISCARD _CONSTEXPR17 bool operator>(const _Array_const_iterator& _Right) const noexcept {
return _Right < *this;
}
_NODISCARD _CONSTEXPR17 bool operator<=(const _Array_const_iterator& _Right) const noexcept {
return !(_Right < *this);
}
_NODISCARD _CONSTEXPR17 bool operator>=(const _Array_const_iterator& _Right) const noexcept {
return !(*this < _Right);
}
#endif // !_HAS_CXX20
using _Prevent_inheriting_unwrap = _Array_const_iterator;
_NODISCARD constexpr pointer _Unwrapped() const noexcept {
return _Ptr;
}
static constexpr bool _Unwrap_when_unverified = true;
constexpr void _Seek_to(pointer _It) noexcept {
_Ptr = _It;
}
private:
pointer _Ptr; // beginning of array
#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv
_CONSTEXPR17 _Array_const_iterator() noexcept : _Ptr(), _Idx(0) {}
_CONSTEXPR17 explicit _Array_const_iterator(pointer _Parg, size_t _Off = 0) noexcept : _Ptr(_Parg), _Idx(_Off) {}
_NODISCARD _CONSTEXPR17 reference operator*() const noexcept {
return *operator->();
}
_NODISCARD _CONSTEXPR17 pointer operator->() const noexcept {
_STL_VERIFY(_Ptr, "cannot dereference value-initialized array iterator");
_STL_VERIFY(_Idx < _Size, "cannot dereference out of range array iterator");
return _Ptr + _Idx;
}
_CONSTEXPR17 _Array_const_iterator& operator++() noexcept {
_STL_VERIFY(_Ptr, "cannot increment value-initialized array iterator");
_STL_VERIFY(_Idx < _Size, "cannot increment array iterator past end");
++_Idx;
return *this;
}
_CONSTEXPR17 _Array_const_iterator operator++(int) noexcept {
_Array_const_iterator _Tmp = *this;
++*this;
return _Tmp;
}
_CONSTEXPR17 _Array_const_iterator& operator--() noexcept {
_STL_VERIFY(_Ptr, "cannot decrement value-initialized array iterator");
_STL_VERIFY(_Idx != 0, "cannot decrement array iterator before begin");
--_Idx;
return *this;
}
_CONSTEXPR17 _Array_const_iterator operator--(int) noexcept {
_Array_const_iterator _Tmp = *this;
--*this;
return _Tmp;
}
constexpr void _Verify_offset(const ptrdiff_t _Off) const noexcept {
if (_Off != 0) {
_STL_VERIFY(_Ptr, "cannot seek value-initialized array iterator");
}
if (_Off < 0) {
_STL_VERIFY(_Idx >= size_t{0} - static_cast<size_t>(_Off), "cannot seek array iterator before begin");
}
if (_Off > 0) {
_STL_VERIFY(_Size - _Idx >= static_cast<size_t>(_Off), "cannot seek array iterator after end");
}
}
_CONSTEXPR17 _Array_const_iterator& operator+=(const ptrdiff_t _Off) noexcept {
_Verify_offset(_Off);
_Idx += static_cast<size_t>(_Off);
return *this;
}
_NODISCARD _CONSTEXPR17 _Array_const_iterator operator+(const ptrdiff_t _Off) const noexcept {
_Array_const_iterator _Tmp = *this;
return _Tmp += _Off;
}
_CONSTEXPR17 _Array_const_iterator& operator-=(const ptrdiff_t _Off) noexcept {
return *this += -_Off;
}
_NODISCARD _CONSTEXPR17 _Array_const_iterator operator-(const ptrdiff_t _Off) const noexcept {
_Array_const_iterator _Tmp = *this;
return _Tmp -= _Off;
}
_NODISCARD _CONSTEXPR17 ptrdiff_t operator-(const _Array_const_iterator& _Right) const noexcept {
_Compat(_Right);
return static_cast<ptrdiff_t>(_Idx - _Right._Idx);
}
_NODISCARD _CONSTEXPR17 reference operator[](const ptrdiff_t _Off) const noexcept {
return *(*this + _Off);
}
_NODISCARD _CONSTEXPR17 bool operator==(const _Array_const_iterator& _Right) const noexcept {
_Compat(_Right);
return _Idx == _Right._Idx;
}
#if _HAS_CXX20
_NODISCARD constexpr strong_ordering operator<=>(const _Array_const_iterator& _Right) const noexcept {
_Compat(_Right);
return _Idx <=> _Right._Idx;
}
#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv
_NODISCARD _CONSTEXPR17 bool operator!=(const _Array_const_iterator& _Right) const noexcept {
return !(*this == _Right);
}
_NODISCARD _CONSTEXPR17 bool operator<(const _Array_const_iterator& _Right) const noexcept {
_Compat(_Right);
return _Idx < _Right._Idx;
}
_NODISCARD _CONSTEXPR17 bool operator>(const _Array_const_iterator& _Right) const noexcept {
return _Right < *this;
}
_NODISCARD _CONSTEXPR17 bool operator<=(const _Array_const_iterator& _Right) const noexcept {
return !(_Right < *this);
}
_NODISCARD _CONSTEXPR17 bool operator>=(const _Array_const_iterator& _Right) const noexcept {
return !(*this < _Right);
}
#endif // !_HAS_CXX20
_CONSTEXPR17 void _Compat(const _Array_const_iterator& _Right) const noexcept { // test for compatible iterator pair
_STL_VERIFY(_Ptr == _Right._Ptr, "array iterators incompatible");
}
using _Prevent_inheriting_unwrap = _Array_const_iterator;
_NODISCARD constexpr pointer _Unwrapped() const noexcept {
return _Ptr + _Idx;
}
constexpr void _Verify_with(const _Array_const_iterator& _Last) const noexcept {
// note _Compat check inside operator<=
_STL_VERIFY(*this <= _Last, "array iterator range transposed");
}
constexpr void _Seek_to(pointer _It) noexcept {
_Idx = static_cast<size_t>(_It - _Ptr);
}
private:
pointer _Ptr; // beginning of array
size_t _Idx; // offset into array
#endif // _ITERATOR_DEBUG_LEVEL == 0
};
#if _ITERATOR_DEBUG_LEVEL != 0
template <class _Ty, size_t _Size>
constexpr void _Verify_range(
const _Array_const_iterator<_Ty, _Size>& _First, const _Array_const_iterator<_Ty, _Size>& _Last) noexcept {
// TRANSITION, CUDA
_First._Verify_with(_Last);
}
#endif // _ITERATOR_DEBUG_LEVEL != 0
/// 迭代器模板特化
template <class _Ty, size_t _Size>
_NODISCARD _CONSTEXPR17 _Array_const_iterator<_Ty, _Size> operator+(
const ptrdiff_t _Off, _Array_const_iterator<_Ty, _Size> _Next) noexcept {
return _Next += _Off;
}
#if _HAS_CXX20
template <class _Ty, size_t _Size>
struct pointer_traits<_Array_const_iterator<_Ty, _Size>> {
using pointer = _Array_const_iterator<_Ty, _Size>;
using element_type = const _Ty;
using difference_type = ptrdiff_t;
_NODISCARD static constexpr element_type* to_address(const pointer _Iter) noexcept {
return _Iter._Unwrapped();
}
};
#endif // _HAS_CXX20
/// 定义子类:非常迭代器
template <class _Ty, size_t _Size>
class _Array_iterator : public _Array_const_iterator<_Ty, _Size> {
public:
using _Mybase = _Array_const_iterator<_Ty, _Size>;
#ifdef __cpp_lib_concepts
using iterator_concept = contiguous_iterator_tag;
#endif // __cpp_lib_concepts
using iterator_category = random_access_iterator_tag;
using value_type = _Ty;
using difference_type = ptrdiff_t;
using pointer = _Ty*;
using reference = _Ty&;
enum { _EEN_SIZE = _Size }; // helper for expression evaluator
_CONSTEXPR17 _Array_iterator() noexcept {}
_CONSTEXPR17 explicit _Array_iterator(pointer _Parg, size_t _Off = 0) noexcept : _Mybase(_Parg, _Off) {}
_NODISCARD _CONSTEXPR17 reference operator*() const noexcept {
return const_cast<reference>(_Mybase::operator*());
}
_NODISCARD _CONSTEXPR17 pointer operator->() const noexcept {
return const_cast<pointer>(_Mybase::operator->()); // 去常
}
// 前++ 重载
_CONSTEXPR17 _Array_iterator& operator++() noexcept {
_Mybase::operator++();
return *this;
}
// 后加加重载
_CONSTEXPR17 _Array_iterator operator++(int) noexcept {
_Array_iterator _Tmp = *this;
_Mybase::operator++();
return _Tmp;
}
// 前减减重载
_CONSTEXPR17 _Array_iterator& operator--() noexcept {
_Mybase::operator--();
return *this;
}
// 后减减重载
_CONSTEXPR17 _Array_iterator operator--(int) noexcept {
_Array_iterator _Tmp = *this;
_Mybase::operator--();
return _Tmp;
}
_CONSTEXPR17 _Array_iterator& operator+=(const ptrdiff_t _Off) noexcept {
_Mybase::operator+=(_Off);
return *this;
}
_NODISCARD _CONSTEXPR17 _Array_iterator operator+(const ptrdiff_t _Off) const noexcept {
_Array_iterator _Tmp = *this;
return _Tmp += _Off;
}
_CONSTEXPR17 _Array_iterator& operator-=(const ptrdiff_t _Off) noexcept {
_Mybase::operator-=(_Off);
return *this;
}
using _Mybase::operator-;
_NODISCARD _CONSTEXPR17 _Array_iterator operator-(const ptrdiff_t _Off) const noexcept {
_Array_iterator _Tmp = *this;
return _Tmp -= _Off;
}
// 下标操作符重载
_NODISCARD _CONSTEXPR17 reference operator[](const ptrdiff_t _Off) const noexcept {
return const_cast<reference>(_Mybase::operator[](_Off));
}
using _Prevent_inheriting_unwrap = _Array_iterator;
_NODISCARD constexpr pointer _Unwrapped() const noexcept {
return const_cast<pointer>(_Mybase::_Unwrapped());
}
};
template <class _Ty, size_t _Size>
_NODISCARD _CONSTEXPR17 _Array_iterator<_Ty, _Size> operator+(
const ptrdiff_t _Off, _Array_iterator<_Ty, _Size> _Next) noexcept {
return _Next += _Off;
}
#if _HAS_CXX20
template <class _Ty, size_t _Size>
struct pointer_traits<_Array_iterator<_Ty, _Size>> {
using pointer = _Array_iterator<_Ty, _Size>;
using element_type = _Ty;
using difference_type = ptrdiff_t;
_NODISCARD static constexpr element_type* to_address(const pointer _Iter) noexcept {
return _Iter._Unwrapped();
}
};
#endif // _HAS_CXX20
/// 定义数组模板
template <class _Ty, size_t _Size>
class array { // fixed size array of values
public:
using value_type = _Ty;
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = _Ty*;
using const_pointer = const _Ty*;
using reference = _Ty&;
using const_reference = const _Ty&;
using iterator = _Array_iterator<_Ty, _Size>;
using const_iterator = _Array_const_iterator<_Ty, _Size>;
using reverse_iterator = _STD reverse_iterator<iterator>;
using const_reverse_iterator = _STD reverse_iterator<const_iterator>;
#if _HAS_TR1_NAMESPACE
_DEPRECATE_TR1_NAMESPACE void assign(const _Ty& _Value) {
_STD fill_n(_Elems, _Size, _Value);
}
#endif // _HAS_TR1_NAMESPACE
_CONSTEXPR20 void fill(const _Ty& _Value) {
_STD fill_n(_Elems, _Size, _Value);
}
_CONSTEXPR20 void swap(array& _Other) noexcept(_Is_nothrow_swappable<_Ty>::value) {
_Swap_ranges_unchecked(_Elems, _Elems + _Size, _Other._Elems);
}
_NODISCARD _CONSTEXPR17 iterator begin() noexcept {
return iterator(_Elems, 0);
}
_NODISCARD _CONSTEXPR17 const_iterator begin() const noexcept {
return const_iterator(_Elems, 0);
}
_NODISCARD _CONSTEXPR17 iterator end() noexcept {
return iterator(_Elems, _Size);
}
_NODISCARD _CONSTEXPR17 const_iterator end() const noexcept {
return const_iterator(_Elems, _Size);
}
_NODISCARD _CONSTEXPR17 reverse_iterator rbegin() noexcept {
return reverse_iterator(end());
}
_NODISCARD _CONSTEXPR17 const_reverse_iterator rbegin() const noexcept {
return const_reverse_iterator(end());
}
_NODISCARD _CONSTEXPR17 reverse_iterator rend() noexcept {
return reverse_iterator(begin());
}
_NODISCARD _CONSTEXPR17 const_reverse_iterator rend() const noexcept {
return const_reverse_iterator(begin());
}
_NODISCARD _CONSTEXPR17 const_iterator cbegin() const noexcept {
return begin();
}
_NODISCARD _CONSTEXPR17 const_iterator cend() const noexcept {
return end();
}
_NODISCARD _CONSTEXPR17 const_reverse_iterator crbegin() const noexcept {
return rbegin();
}
_NODISCARD _CONSTEXPR17 const_reverse_iterator crend() const noexcept {
return rend();
}
_CONSTEXPR17 _Ty* _Unchecked_begin() noexcept {
return _Elems;
}
_CONSTEXPR17 const _Ty* _Unchecked_begin() const noexcept {
return _Elems;
}
_CONSTEXPR17 _Ty* _Unchecked_end() noexcept {
return _Elems + _Size;
}
_CONSTEXPR17 const _Ty* _Unchecked_end() const noexcept {
return _Elems + _Size;
}
_NODISCARD constexpr size_type size() const noexcept {
return _Size;
}
_NODISCARD constexpr size_type max_size() const noexcept {
return _Size;
}
_NODISCARD constexpr bool empty() const noexcept {
return false;
}
_NODISCARD _CONSTEXPR17 reference at(size_type _Pos) {
if (_Size <= _Pos) {
_Xran();
}
return _Elems[_Pos];
}
_NODISCARD constexpr const_reference at(size_type _Pos) const {
if (_Size <= _Pos) {
_Xran();
}
return _Elems[_Pos];
}
_NODISCARD _CONSTEXPR17 reference operator[](_In_range_(0, _Size - 1) size_type _Pos) noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Pos < _Size, "array subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _Elems[_Pos];
}
_NODISCARD constexpr const_reference operator[](_In_range_(0, _Size - 1) size_type _Pos) const noexcept
/* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Pos < _Size, "array subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _Elems[_Pos];
}
_NODISCARD _CONSTEXPR17 reference front() noexcept /* strengthened */ {
return _Elems[0];
}
_NODISCARD constexpr const_reference front() const noexcept /* strengthened */ {
return _Elems[0];
}
_NODISCARD _CONSTEXPR17 reference back() noexcept /* strengthened */ {
return _Elems[_Size - 1];
}
_NODISCARD constexpr const_reference back() const noexcept /* strengthened */ {
return _Elems[_Size - 1];
}
_NODISCARD _CONSTEXPR17 _Ty* data() noexcept {
return _Elems;
}
_NODISCARD _CONSTEXPR17 const _Ty* data() const noexcept {
return _Elems;
}
[[noreturn]] void _Xran() const {
_Xout_of_range("invalid array<T, N> subscript");
}
_Ty _Elems[_Size];
};
#if _HAS_CXX17
template <class _First, class... _Rest>
struct _Enforce_same {
static_assert(conjunction_v<is_same<_First, _Rest>...>,
"N4687 26.3.7.2 [array.cons]/2: "
"Requires: (is_same_v<T, U> && ...) is true. Otherwise the program is ill-formed.");
using type = _First;
};
/// 检查数组中元素类型与第一个要严格一致
template <class _First, class... _Rest>
array(_First, _Rest...) -> array<typename _Enforce_same<_First, _Rest...>::type, 1 + sizeof...(_Rest)>;
#endif // _HAS_CXX17
/// 数组模板偏特化
template <class _Ty>
class array<_Ty, 0> {
public:
using value_type = _Ty;
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = _Ty*;
using const_pointer = const _Ty*;
using reference = _Ty&;
using const_reference = const _Ty&;
using iterator = _Array_iterator<_Ty, 0>;
using const_iterator = _Array_const_iterator<_Ty, 0>;
using reverse_iterator = _STD reverse_iterator<iterator>;
using const_reverse_iterator = _STD reverse_iterator<const_iterator>;
#if _HAS_TR1_NAMESPACE
_DEPRECATE_TR1_NAMESPACE void assign(const _Ty&) {}
#endif // _HAS_TR1_NAMESPACE
_CONSTEXPR20 void fill(const _Ty&) {}
_CONSTEXPR20 void swap(array&) noexcept {}
_NODISCARD _CONSTEXPR17 iterator begin() noexcept {
return iterator{};
}
_NODISCARD _CONSTEXPR17 const_iterator begin() const noexcept {
return const_iterator{};
}
_NODISCARD _CONSTEXPR17 iterator end() noexcept {
return iterator{};
}
_NODISCARD _CONSTEXPR17 const_iterator end() const noexcept {
return const_iterator{};
}
_NODISCARD _CONSTEXPR17 reverse_iterator rbegin() noexcept {
return reverse_iterator(end());
}
_NODISCARD _CONSTEXPR17 const_reverse_iterator rbegin() const noexcept {
return const_reverse_iterator(end());
}
_NODISCARD _CONSTEXPR17 reverse_iterator rend() noexcept {
return reverse_iterator(begin());
}
_NODISCARD _CONSTEXPR17 const_reverse_iterator rend() const noexcept {
return const_reverse_iterator(begin());
}
_NODISCARD _CONSTEXPR17 const_iterator cbegin() const noexcept {
return begin();
}
_NODISCARD _CONSTEXPR17 const_iterator cend() const noexcept {
return end();
}
_NODISCARD _CONSTEXPR17 const_reverse_iterator crbegin() const noexcept {
return rbegin();
}
_NODISCARD _CONSTEXPR17 const_reverse_iterator crend() const noexcept {
return rend();
}
_CONSTEXPR17 _Ty* _Unchecked_begin() noexcept {
return nullptr;
}
_CONSTEXPR17 const _Ty* _Unchecked_begin() const noexcept {
return nullptr;
}
_CONSTEXPR17 _Ty* _Unchecked_end() noexcept {
return nullptr;
}
_CONSTEXPR17 const _Ty* _Unchecked_end() const noexcept {
return nullptr;
}
_NODISCARD constexpr size_type size() const noexcept {
return 0;
}
_NODISCARD constexpr size_type max_size() const noexcept {
return 0;
}
_NODISCARD constexpr bool empty() const noexcept {
return true;
}
[[noreturn]] reference at(size_type) {
_Xran();
}
[[noreturn]] const_reference at(size_type) const {
_Xran();
}
_NODISCARD reference operator[](size_type) noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_REPORT_ERROR("array subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _Elems[0];
}
_NODISCARD const_reference operator[](size_type) const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_REPORT_ERROR("array subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _Elems[0];
}
_NODISCARD reference front() noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_REPORT_ERROR("array<T, 0>::front() invalid");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _Elems[0];
}
_NODISCARD const_reference front() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_REPORT_ERROR("array<T, 0>::front() invalid");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _Elems[0];
}
_NODISCARD reference back() noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_REPORT_ERROR("array<T, 0>::back() invalid");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _Elems[0];
}
_NODISCARD const_reference back() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_REPORT_ERROR("array<T, 0>::back() invalid");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _Elems[0];
}
_NODISCARD _CONSTEXPR17 _Ty* data() noexcept {
return nullptr;
}
_NODISCARD _CONSTEXPR17 const _Ty* data() const noexcept {
return nullptr;
}
[[noreturn]] void _Xran() const {
_Xout_of_range("invalid array<T, 0> subscript");
}
_Ty _Elems[1];
};
template <class _Ty, size_t _Size, enable_if_t<_Size == 0 || _Is_swappable<_Ty>::value, int> = 0>
_CONSTEXPR20 void swap(array<_Ty, _Size>& _Left, array<_Ty, _Size>& _Right) noexcept(noexcept(_Left.swap(_Right))) {
return _Left.swap(_Right);
}
template <class _Ty, size_t _Size>
_NODISCARD _CONSTEXPR20 bool operator==(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) {
#ifdef __EDG__ // TRANSITION, VSO-1161663
return _STD equal(_Left.begin(), _Left.end(), _Right.begin());
#else // ^^^ workaround / no workaround vvv
return _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin());
#endif // ^^^ no workaround ^^^
}
#if !_HAS_CXX20
template <class _Ty, size_t _Size>
_NODISCARD bool operator!=(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) {
return !(_Left == _Right);
}
#endif // !_HAS_CXX20
#ifdef __cpp_lib_concepts
template <class _Ty, size_t _Size>
_NODISCARD constexpr _Synth_three_way_result<_Ty> operator<=>(
const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) {
#ifdef __EDG__ // TRANSITION, VSO-1161663
return _STD lexicographical_compare_three_way(
_Left.begin(), _Left.end(), _Right.begin(), _Right.end(), _Synth_three_way{});
#else // ^^^ workaround / no workaround vvv
return _STD lexicographical_compare_three_way(_Left._Unchecked_begin(), _Left._Unchecked_end(),
_Right._Unchecked_begin(), _Right._Unchecked_end(), _Synth_three_way{});
#endif // ^^^ no workaround ^^^
}
#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv
template <class _Ty, size_t _Size>
_NODISCARD _CONSTEXPR20 bool operator<(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) {
#ifdef __EDG__ // TRANSITION, VSO-1161663
return _STD lexicographical_compare(_Left.begin(), _Left.end(), _Right.begin(), _Right.end());
#else // ^^^ workaround / no workaround vvv
return _STD lexicographical_compare(
_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin(), _Right._Unchecked_end());
#endif // ^^^ no workaround ^^^
}
template <class _Ty, size_t _Size>
_NODISCARD _CONSTEXPR20 bool operator>(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) {
return _Right < _Left;
}
template <class _Ty, size_t _Size>
_NODISCARD _CONSTEXPR20 bool operator<=(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) {
return !(_Right < _Left);
}
template <class _Ty, size_t _Size>
_NODISCARD _CONSTEXPR20 bool operator>=(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) {
return !(_Left < _Right);
}
#endif // ^^^ !defined(__cpp_lib_concepts) ^^^
#if _HAS_CXX20
template <class _Ty, size_t _Size, size_t... _Idx>
_NODISCARD constexpr array<remove_cv_t<_Ty>, _Size> _To_array_lvalue_impl(
_Ty (&_Array)[_Size], index_sequence<_Idx...>) {
return {{_Array[_Idx]...}};
}
template <class _Ty, size_t _Size, size_t... _Idx>
_NODISCARD constexpr array<remove_cv_t<_Ty>, _Size> _To_array_rvalue_impl(
_Ty(&&_Array)[_Size], index_sequence<_Idx...>) {
return {{_STD move(_Array[_Idx])...}};
}
template <class _Ty, size_t _Size>
_NODISCARD constexpr array<remove_cv_t<_Ty>, _Size> to_array(_Ty (&_Array)[_Size]) {
static_assert(!is_array_v<_Ty>, "N4830 [array.creation]/1: "
"to_array does not accept multidimensional arrays.");
static_assert(is_constructible_v<_Ty, _Ty&>, "N4830 [array.creation]/1: "
"to_array requires copy constructible elements.");
return _To_array_lvalue_impl(_Array, make_index_sequence<_Size>{});
}
template <class _Ty, size_t _Size>
_NODISCARD constexpr array<remove_cv_t<_Ty>, _Size> to_array(_Ty(&&_Array)[_Size]) {
static_assert(!is_array_v<_Ty>, "N4830 [array.creation]/4: "
"to_array does not accept multidimensional arrays.");
static_assert(is_move_constructible_v<_Ty>, "N4830 [array.creation]/4: "
"to_array requires move constructible elements.");
return _To_array_rvalue_impl(_STD move(_Array), make_index_sequence<_Size>{});
}
#endif // _HAS_CXX20
template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr _Ty& get(array<_Ty, _Size>& _Arr) noexcept {
static_assert(_Idx < _Size, "array index out of bounds");
return _Arr._Elems[_Idx];
}
template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr const _Ty& get(const array<_Ty, _Size>& _Arr) noexcept {
static_assert(_Idx < _Size, "array index out of bounds");
return _Arr._Elems[_Idx];
}
template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr _Ty&& get(array<_Ty, _Size>&& _Arr) noexcept {
static_assert(_Idx < _Size, "array index out of bounds");
return _STD move(_Arr._Elems[_Idx]);
}
template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr const _Ty&& get(const array<_Ty, _Size>&& _Arr) noexcept {
static_assert(_Idx < _Size, "array index out of bounds");
return _STD move(_Arr._Elems[_Idx]);
}
#if _HAS_TR1_NAMESPACE
namespace _DEPRECATE_TR1_NAMESPACE tr1 {
using _STD array;
using _STD get;
} // namespace tr1
#endif // _HAS_TR1_NAMESPACE
_STD_END
#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)
#endif // _STL_COMPILER_PREPROCESSOR
#endif // _ARRAY_
从源码来看,非常经典而简洁,在我们平时自己使用元编程技巧时,有不错的借鉴意义。而且这一段难度比较低,基本上大家应该都能看得懂。
std::array
在底层实现上,还是依赖于 基础数组 这一数据类型,以下源码可以佐证。
template <class _Ty, size_t _Size>
class array { // fixed size array of values
_Ty _Elems[_Size]; // 数组
};
个人喜欢std::array
的OOP
,不过std::array
也有觉得可以优化的地方,譬如不支持弹性数组的特性,不支持扩容,不支持参数化列表初始化等,不过,这也许正是设计者设计std::array
如此简洁优雅之意图。
编程,不只是技术,深入去思考,会觉得简直就是艺术~
文章来源:https://blog.csdn.net/weixin_39568531/article/details/135216575
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!