1#ifndef DA_VECTOR_TABLE_H
2#define DA_VECTOR_TABLE_H
8#include <initializer_list>
28 using iterator =
typename std::vector< T >::iterator;
29 using const_iterator =
typename std::vector< T >::const_iterator;
30 using reverse_iterator =
typename std::vector< T >::reverse_iterator;
31 using const_reverse_iterator =
typename std::vector< T >::const_reverse_iterator;
36 explicit da_vector_table(std::size_t rows, std::size_t cols = 0,
const T& value = T());
37 da_vector_table(std::initializer_list< std::initializer_list< T > > init);
48 bool empty() const noexcept;
49 std::
size_t size() const noexcept;
50 std::
size_t max_size() const noexcept;
51 void reserve(std::
size_t new_cap);
52 std::
size_t capacity() const noexcept;
56 iterator
begin() noexcept;
57 const_iterator
begin() const noexcept;
58 const_iterator
cbegin() const noexcept;
59 iterator
end() noexcept;
60 const_iterator
end() const noexcept;
61 const_iterator
cend() const noexcept;
62 reverse_iterator
rbegin() noexcept;
63 const_reverse_iterator
rbegin() const noexcept;
64 const_reverse_iterator
crbegin() const noexcept;
65 reverse_iterator
rend() noexcept;
66 const_reverse_iterator
rend() const noexcept;
67 const_reverse_iterator
crend() const noexcept;
70 T& operator()(std::
size_t row, std::
size_t col);
71 const T& operator()(std::
size_t row, std::
size_t col) const;
72 T&
at(std::
size_t row, std::
size_t col);
73 const T&
at(std::
size_t row, std::
size_t col) const;
75 const T&
front() const;
77 const T&
back() const;
79 const T*
data() const noexcept;
82 void assign(std::
size_t rows, std::
size_t cols, const T& value);
83 template< typename InputIt >
84 void assign(InputIt first, InputIt last);
87 template< typename... Args >
90 void clear() noexcept;
96 template< typename InputIt >
98 void append_row(std::initializer_list< T > il);
99 void insert_row(std::
size_t pos, const std::vector< T >& row);
100 void insert_row(std::
size_t pos, std::vector< T >&& row);
106 template< typename InputIt >
109 void insert_column(std::
size_t pos, const std::vector< T >& col);
117 void resize(std::
size_t rows, std::
size_t cols, const T& value = T());
119 void reshape(std::
size_t rows, std::
size_t cols);
122 bool is_rectangular() const noexcept
126 std::vector< T >
get_row(std::size_t row)
const;
127 std::vector< T >
get_column(std::size_t col)
const;
128 void set_row(std::size_t row,
const std::vector< T >& values);
129 void set_column(std::size_t col,
const std::vector< T >& values);
132 std::vector< T > data_;
137 std::size_t index(std::size_t row, std::size_t col)
const noexcept;
138 void check_bounds(std::size_t row, std::size_t col)
const;
139 void check_row_bounds(std::size_t row)
const;
140 void check_column_bounds(std::size_t col)
const;
156template<
typename T >
176template<
typename T >
178 : data_(rows * cols, value), rows_(rows), cols_(cols)
196template<
typename T >
198 : rows_(init.size()), cols_(0)
201 for (
const auto& row : init) {
202 if (row.size() > cols_) {
208 data_.resize(rows_ * cols_);
211 std::size_t row_idx = 0;
212 for (
const auto& row : init) {
213 std::size_t col_idx = 0;
214 for (
const auto& value : row) {
215 data_[ index(row_idx, col_idx) ] = value;
219 for (; col_idx < cols_; ++col_idx) {
220 data_[ index(row_idx, col_idx) ] = T();
237template<
typename T >
239 : data_(other.data_), rows_(other.rows_), cols_(other.cols_)
257template<
typename T >
259 : data_(std::move(other.data_)), rows_(other.rows_), cols_(other.cols_)
277template<
typename T >
280 if (
this != &other) {
300template<
typename T >
303 if (
this != &other) {
304 data_ = std::move(other.data_);
325template<
typename T >
328 return data_.empty();
341template<
typename T >
357template<
typename T >
360 return data_.max_size();
374template<
typename T >
377 data_.reserve(new_cap);
391template<
typename T >
394 return data_.capacity();
409template<
typename T >
412 data_.shrink_to_fit();
428template<
typename T >
431 return data_.begin();
447template<
typename T >
450 return data_.begin();
466template<
typename T >
469 return data_.cbegin();
485template<
typename T >
504template<
typename T >
523template<
typename T >
542template<
typename T >
545 return data_.rbegin();
561template<
typename T >
564 return data_.rbegin();
580template<
typename T >
583 return data_.crbegin();
599template<
typename T >
618template<
typename T >
637template<
typename T >
640 return data_.crend();
657template<
typename T >
660 return data_[ index(row, col) ];
677template<
typename T >
680 return data_[ index(row, col) ];
704template<
typename T >
707 check_bounds(row, col);
708 return data_[ index(row, col) ];
732template<
typename T >
735 check_bounds(row, col);
736 return data_[ index(row, col) ];
750template<
typename T >
753 return data_.front();
767template<
typename T >
770 return data_.front();
784template<
typename T >
801template<
typename T >
821template<
typename T >
841template<
typename T >
860template<
typename T >
863 data_.assign(rows * cols, value);
886template<
typename T >
887template<
typename InputIt >
890 data_.assign(first, last);
906template<
typename T >
909 data_.push_back(value);
926template<
typename T >
929 data_.push_back(std::move(value));
947template<
typename T >
948template<
typename... Args >
951 data_.emplace_back(std::forward< Args >(args)...);
966template<
typename T >
983template<
typename T >
1003template<
typename T >
1006 data_.swap(other.data_);
1007 std::swap(rows_, other.rows_);
1008 std::swap(cols_, other.cols_);
1023template<
typename T >
1029 }
else if (row.size() != cols_) {
1030 throw std::invalid_argument(
"Row size must match table column count");
1033 data_.insert(data_.end(), row.begin(), row.end());
1049template<
typename T >
1055 }
else if (row.size() != cols_) {
1056 throw std::invalid_argument(
"Row size must match table column count");
1059 data_.insert(data_.end(), std::make_move_iterator(row.begin()), std::make_move_iterator(row.end()));
1078template<
typename T >
1079template<
typename InputIt >
1082 const std::size_t count = std::distance(first, last);
1086 }
else if (count != cols_) {
1087 throw std::invalid_argument(
"Row size must match table column count");
1090 data_.insert(data_.end(), first, last);
1106template<
typename T >
1112 }
else if (il.size() != cols_) {
1113 throw std::invalid_argument(
"Row size must match table column count");
1116 data_.insert(data_.end(), il.begin(), il.end());
1134template<
typename T >
1137 check_row_bounds(pos);
1142 }
else if (row.size() != cols_) {
1143 throw std::invalid_argument(
"Row size must match table column count");
1147 const std::size_t insert_pos = pos * cols_;
1148 data_.insert(data_.begin() + insert_pos, row.begin(), row.end());
1166template<
typename T >
1169 check_row_bounds(pos);
1174 }
else if (row.size() != cols_) {
1175 throw std::invalid_argument(
"Row size must match table column count");
1179 if (data_.capacity() < data_.size() + cols_) {
1180 data_.reserve(data_.capacity() + std::max(data_.capacity(), cols_ * 2));
1184 const std::size_t insert_pos = pos * cols_;
1185 data_.insert(data_.begin() + insert_pos, std::make_move_iterator(row.begin()), std::make_move_iterator(row.end()));
1201template<
typename T >
1204 check_row_bounds(pos);
1207 const std::size_t start_pos = pos * cols_;
1208 const std::size_t end_pos = start_pos + cols_;
1210 data_.erase(data_.begin() + start_pos, data_.begin() + end_pos);
1230template<
typename InputIt>
1234 const std::size_t count = std::distance(first, last);
1235 if (count != rows_) {
1236 throw std::invalid_argument(
"Column size must match table row count");
1240 std::vector<T> new_data;
1241 new_data.reserve(rows_ * (cols_ + 1));
1245 for (std::size_t i = 0; i < rows_; ++i) {
1246 const std::size_t row_start = i * cols_;
1249 for (std::size_t j = 0; j < cols_; ++j) {
1250 new_data.push_back(std::move(data_[row_start + j]));
1254 new_data.push_back(*it);
1259 data_ = std::move(new_data);
1279 append_column(col.begin(), col.end());
1298 append_column(std::make_move_iterator(col.begin()),
1299 std::make_move_iterator(col.end()));
1318 append_column(il.begin(), il.end());
1335template<
typename T >
1338 check_column_bounds(pos);
1340 if (col.size() != rows_) {
1341 throw std::invalid_argument(
"Column size must match table row count");
1345 std::vector< T > new_data;
1346 new_data.reserve(rows_ * (cols_ + 1));
1349 for (std::size_t i = 0; i < rows_; ++i) {
1350 const std::size_t row_start = i * cols_;
1353 for (std::size_t j = 0; j < pos; ++j) {
1354 new_data.push_back(data_[ row_start + j ]);
1358 new_data.push_back(col[ i ]);
1361 for (std::size_t j = pos; j < cols_; ++j) {
1362 new_data.push_back(data_[ row_start + j ]);
1367 data_ = std::move(new_data);
1388 check_column_bounds(pos);
1390 if (col.size() != rows_) {
1391 throw std::invalid_argument(
"Column size must match table row count");
1395 std::vector<T> new_data;
1396 new_data.reserve(rows_ * (cols_ + 1));
1399 for (std::size_t i = 0; i < rows_; ++i) {
1400 const std::size_t row_start = i * cols_;
1403 for (std::size_t j = 0; j < pos; ++j) {
1404 new_data.push_back(std::move(data_[row_start + j]));
1408 new_data.push_back(std::move(col[i]));
1411 for (std::size_t j = pos; j < cols_; ++j) {
1412 new_data.push_back(std::move(data_[row_start + j]));
1417 data_ = std::move(new_data);
1435template<
typename T >
1438 check_column_bounds(pos);
1441 std::vector< T > new_data;
1442 new_data.reserve(rows_ * (cols_ - 1));
1445 for (std::size_t i = 0; i < rows_; ++i) {
1446 const std::size_t row_start = i * cols_;
1449 for (std::size_t j = 0; j < pos; ++j) {
1450 new_data.push_back(data_[ row_start + j ]);
1454 for (std::size_t j = pos + 1; j < cols_; ++j) {
1455 new_data.push_back(data_[ row_start + j ]);
1460 data_ = std::move(new_data);
1477template<
typename T >
1480 return { rows_, cols_ };
1494template<
typename T >
1511template<
typename T >
1531template<
typename T >
1534 if (rows == rows_ && cols == cols_) {
1539 if (cols == cols_ && rows * cols <= data_.capacity()) {
1542 data_.resize(rows * cols, value);
1545 data_.resize(rows * cols);
1552 std::vector< T > new_data(rows * cols, value);
1554 const std::size_t copy_rows = std::min(rows, rows_);
1555 const std::size_t copy_cols = std::min(cols, cols_);
1557 for (std::size_t i = 0; i < copy_rows; ++i) {
1558 for (std::size_t j = 0; j < copy_cols; ++j) {
1559 new_data[ i * cols + j ] = data_[ i * cols_ + j ];
1563 data_ = std::move(new_data);
1581template<
typename T >
1584 resize(sh.first, sh.second, value);
1601template<
typename T >
1604 if (rows * cols != data_.size()) {
1605 throw std::invalid_argument(
"New shape must have the same number of elements");
1625template<
typename T >
1628 check_row_bounds(row);
1630 std::vector< T > result;
1631 result.reserve(cols_);
1633 const std::size_t start = row * cols_;
1634 for (std::size_t i = 0; i < cols_; ++i) {
1635 result.push_back(data_[ start + i ]);
1654template<
typename T >
1657 check_column_bounds(col);
1659 std::vector< T > result;
1660 result.reserve(rows_);
1662 for (std::size_t i = 0; i < rows_; ++i) {
1663 result.push_back(data_[ i * cols_ + col ]);
1683template<
typename T >
1686 check_row_bounds(row);
1688 if (values.size() != cols_) {
1689 throw std::invalid_argument(
"Number of values must match column count");
1692 const std::size_t start = row * cols_;
1693 for (std::size_t i = 0; i < cols_; ++i) {
1694 data_[ start + i ] = values[ i ];
1712template<
typename T >
1715 check_column_bounds(col);
1717 if (values.size() != rows_) {
1718 throw std::invalid_argument(
"Number of values must match row count");
1721 for (std::size_t i = 0; i < rows_; ++i) {
1722 data_[ i * cols_ + col ] = values[ i ];
1737template<
typename T >
1740 return row * cols_ + col;
1750template<
typename T >
1751void da_vector_table< T >::check_bounds(std::size_t row, std::size_t col)
const
1754 throw std::out_of_range(
"Row index out of range");
1757 throw std::out_of_range(
"Column index out of range");
1767template<
typename T >
1768void da_vector_table< T >::check_row_bounds(std::size_t row)
const
1771 throw std::out_of_range(
"Row index out of range");
1781template<
typename T >
1782void da_vector_table< T >::check_column_bounds(std::size_t col)
const
1785 throw std::out_of_range(
"Column index out of range");
二维表格数据结构,使用一维数组存储以提高缓存友好性
Definition da_vector_table.hpp:22
std::pair< std::size_t, std::size_t > table_index_type
表格形状类型(行数, 列数)
Definition da_vector_table.hpp:25
void swap(da_vector_table &other) noexcept
交换两个表格的内容
Definition da_vector_table.hpp:1004
void append_column(const std::vector< T > &col)
在表格末尾添加一列
Definition da_vector_table.hpp:1276
T & front()
访问表格的第一个元素
Definition da_vector_table.hpp:751
void push_back(const T &value)
在表格末尾添加一个元素
Definition da_vector_table.hpp:907
da_vector_table & operator=(const da_vector_table &other)
拷贝赋值运算符
Definition da_vector_table.hpp:278
void insert_row(std::size_t pos, const std::vector< T > &row)
在指定位置插入一行
Definition da_vector_table.hpp:1135
void insert_column(std::size_t pos, const std::vector< T > &col)
在指定位置插入一列
Definition da_vector_table.hpp:1336
void clear() noexcept
清空表格中的所有元素
Definition da_vector_table.hpp:984
T value_type
元素类型
Definition da_vector_table.hpp:24
T & at(std::size_t row, std::size_t col)
访问指定位置的元素,带边界检查
Definition da_vector_table.hpp:705
const_reverse_iterator crend() const noexcept
返回指向表格第一个元素前一个位置的常量反向迭代器
Definition da_vector_table.hpp:638
void append_row(const std::vector< T > &row)
在表格末尾添加一行
Definition da_vector_table.hpp:1024
void erase_column(std::size_t pos)
移除指定位置的列(高效版本)
Definition da_vector_table.hpp:1436
reverse_iterator rbegin() noexcept
返回指向表格最后一个元素的反向迭代器
Definition da_vector_table.hpp:543
void reshape(std::size_t rows, std::size_t cols)
改变表格形状而不改变数据总量
Definition da_vector_table.hpp:1602
std::size_t max_size() const noexcept
返回表格可容纳的最大元素数
Definition da_vector_table.hpp:358
std::size_t capacity() const noexcept
返回当前分配的存储容量
Definition da_vector_table.hpp:392
T * data() noexcept
返回指向底层数组的指针
Definition da_vector_table.hpp:822
void resize(std::size_t rows, std::size_t cols, const T &value=T())
调整表格大小
Definition da_vector_table.hpp:1532
std::size_t column_count() const noexcept
获取表格的列数
Definition da_vector_table.hpp:1512
std::vector< T > get_row(std::size_t row) const
获取指定行的数据
Definition da_vector_table.hpp:1626
iterator end() noexcept
返回指向表格尾后位置的迭代器
Definition da_vector_table.hpp:486
const_iterator cbegin() const noexcept
返回指向表格第一个元素的常量迭代器
Definition da_vector_table.hpp:467
da_vector_table()
默认构造函数
Definition da_vector_table.hpp:157
void assign(std::size_t rows, std::size_t cols, const T &value)
分配新内容替换当前内容
Definition da_vector_table.hpp:861
void shrink_to_fit()
请求移除未使用的容量
Definition da_vector_table.hpp:410
table_index_type shape() const noexcept
获取表格的形状(行数和列数)
Definition da_vector_table.hpp:1478
iterator begin() noexcept
返回指向表格第一个元素的迭代器
Definition da_vector_table.hpp:429
std::size_t row_count() const noexcept
获取表格的行数
Definition da_vector_table.hpp:1495
void set_row(std::size_t row, const std::vector< T > &values)
设置指定行的数据
Definition da_vector_table.hpp:1684
bool empty() const noexcept
检查表格是否为空
Definition da_vector_table.hpp:326
const_iterator cend() const noexcept
返回指向表格尾后位置的常量迭代器
Definition da_vector_table.hpp:524
void emplace_back(Args &&... args)
在表格末尾原位构造一个元素
Definition da_vector_table.hpp:949
std::vector< T > get_column(std::size_t col) const
获取指定列的数据
Definition da_vector_table.hpp:1655
void erase_row(std::size_t pos)
移除指定位置的行
Definition da_vector_table.hpp:1202
reverse_iterator rend() noexcept
返回指向表格第一个元素前一个位置的反向迭代器
Definition da_vector_table.hpp:600
T & back()
访问表格的最后一个元素
Definition da_vector_table.hpp:785
void pop_back()
移除表格的最后一个元素
Definition da_vector_table.hpp:967
std::size_t size() const noexcept
返回表格中的元素总数
Definition da_vector_table.hpp:342
void reserve(std::size_t new_cap)
预留存储空间
Definition da_vector_table.hpp:375
T & operator()(std::size_t row, std::size_t col)
访问指定位置的元素(函数调用运算符)
Definition da_vector_table.hpp:658
const_reverse_iterator crbegin() const noexcept
返回指向表格最后一个元素的常量反向迭代器
Definition da_vector_table.hpp:581
void set_column(std::size_t col, const std::vector< T > &values)
设置指定列的数据
Definition da_vector_table.hpp:1713
序列化类都是带异常的,使用中需要处理异常
Definition AppMainWindow.cpp:44