为什么 MojVektor 中的 Iterator 类(类似于 std::vector)不能与 std::copy 算法一起使用?
MojVektor.hpp
#pragma once
#include <iostream>
#include <initializer_list>
#include <algorithm>
#include <Iterator>
template <typename T>
class MojVektor {
private:
size_t capacity_;
size_t size_;
T* arr_;
void realoc() {
capacity_ *= 2;
T* tempArr = arr_;
arr_ = new T[capacity_];
std::copy(tempArr, tempArr + size_, arr_);
delete[] tempArr;
return;
}
public:
class Iterator;
MojVektor() : capacity_{ 10 }, size_{ 0 }, arr_{ new T[capacity_] } {};
MojVektor(const std::initializer_list<T>& list) : capacity_{ list.size() }, size_{ list.size() }, arr_{ new T[capacity_] } {
std::copy(list.begin(), list.end(), arr_);
return;
}
MojVektor(const MojVektor& second) : capacity_{ second.capacity_ }, size_{ second.size_ }, arr_{ new T[capacity_] } {
std::copy(second.arr_, second.arr_ + size_, arr_);
return;
}
MojVektor& operator=(const MojVektor& second) {
capacity_ = second.capacity_;
size_ = second.size_;
arr_ = new T[capacity_];
std::copy(second.arr_, second.arr_ + size_, arr_);
return *this;
}
MojVektor(MojVektor&& second) : capacity_{ std::move(second.capacity_) }, size_{ std::move(second.size_) }, arr_{ std::move(second.arr_) } {
second.capacity_ = 0;
second.size_ = 0;
second.arr_ = nullptr;
return;
}
MojVektor& operator=(MojVektor&& second) {
capacity_ = std::move(second.capacity_);
size_ = std::move(second.size_);
arr_ = std::move(second.arr_);
second.capacity_ = 0;
second.size_ = 0;
second.arr_ = nullptr;
return *this;
}
~MojVektor() {
delete[] arr_;
size_ = 0;
capacity_ = 0;
return;
}
MojVektor& push_back(const T& e) {
if (arr_ == nullptr) {
capacity_ = 10;
arr_ = new T[capacity_];
}
if (size_ >= capacity_) {
realoc();
}
arr_[size_] = e;
++size_;
return *this;
}
MojVektor& push_front(const T& e) {
if (arr_ == nullptr) {
capacity_ = 10;
arr_ = new T[capacity_];
}
if (size_ >= capacity_) {
realoc();
}
for (T* endIndex = arr_ + size_ - 1; endIndex >= arr_; --endIndex) {
*(endIndex + 1) = std::move(*(endIndex));
}
*(arr_) = e;
++size_;
return *this;
}
MojVektor& push_back(T&& e) {
if (arr_ == nullptr) {
capacity_ = 10;
arr_ = new T[capacity_];
}
if (size_ >= capacity_) {
realoc();
}
arr_[size_] = std::move(e);
++size_;
return *this;
}
MojVektor& push_front(T&& e) {
if (arr_ == nullptr) {
capacity_ = 10;
arr_ = new T[capacity_];
}
if (size_ >= capacity_) {
realoc();
}
for (T* endIndex = arr_ + size_ - 1; endIndex >= arr_; --endIndex) {
*(endIndex + 1) = std::move(*(endIndex));
}
*(arr_) = std::move(e);
++size_;
return *this;
}
size_t size() const {
return size_;
}
T& at(size_t index) const {
if (index < 0 || index > size_ - 1) {
throw std::out_of_range("Index out of range!");
}
return *(arr_ + index);
}
T& operator[](size_t index) const {
return *(arr_ + index);
}
void clear() {
capacity_ = 0;
size_ = 0;
delete[] arr_;
arr_ = nullptr;
return;
}
void resize(size_t newSize, const T& difference_value) {
if (newSize < size_) {
size_ = newSize;
}
else if (newSize > size_) {
T* tempArr = arr_;
capacity_ = newSize;
arr_ = new T[capacity_];
std::copy(tempArr, tempArr + size_, arr_);
while (size_ < newSize) {
arr_[size_] = difference_value;
++size_;
}
}
return;
}
MojVektor& pop_back() {
if (size_ == 0) {
throw std::out_of_range("Vector is empty!");
}
--size_;
return *this;
}
MojVektor& pop_front() {
if (size_ == 0) {
throw std::out_of_range("Vector is empty!");
}
for (T* beginIndex = arr_; beginIndex < arr_ + size_; ++beginIndex) {
*(beginIndex) = std::move(*(beginIndex + 1));
}
--size_;
return *this;
}
T& back() const {
if (size_ == 0) {
throw std::out_of_range("Vector is empty!");
}
return arr_[size_ - 1];
}
T& front() const {
if (size_ == 0) {
throw std::out_of_range("Vector is empty!");
}
return *arr_;
}
bool empty() const {
return size_ == 0;
}
size_t capacity() const {
return capacity_;
}
bool operator==(const MojVektor& second) const {
if (size_ != second.size_) {
return false;
}
for (size_t i = 0; i < size_; ++i) {
if ((this->operator[](i)) != second[i]) {
return false;
}
}
return true;
}
bool operator!=(const MojVektor& second) const {
return !(this->operator==(second));
}
bool full() const {
return size_ == capacity_;
}
MojVektor subvector(Iterator beginIt, Iterator endIt) const {
if (beginIt < begin() || endIt > end()) {
throw std::out_of_range("Iterators out of range!");
}
MojVektor v;
while (beginIt != endIt) {
v.push_back(*beginIt);
++beginIt;
}
return v;
}
Iterator begin() const {
return Iterator(arr_);
}
Iterator end() const {
return Iterator(arr_ + size_);
}
Iterator find(const T& value) const {
Iterator it = begin();
while (it != end()) {
if (*(it) == value) {
return it;
}
++it;
}
return it;
}
Iterator erase(Iterator pos) {
if (pos < begin() || pos > end()) {
throw std::out_of_range("Iterator out of range!");
}
if (pos == end()) {
return end();
}
Iterator it{ pos };
while (it != end()) {
*(it) = std::move(*(it + 1));
++it;
}
--size_;
return pos;
}
Iterator insert(Iterator pos, const T& e) {
size_t index = pos - begin();
if (index < 0 || index >= size_) {
throw std::out_of_range("Iterator out of range!");
}
if (size_ >= capacity_) {
realoc();
}
if (index == 0) {
push_front(e);
}
else {
for (size_t i = size_; i >= index; --i) {
*(arr_ + i + 1) = std::move(*(arr_ + i));
}
arr_[index] = e;
++size_;
}
return Iterator{ arr_ + index };
}
Iterator insert(Iterator pos, T&& e) {
size_t index = pos - begin();
if (index < 0 || index >= size_) {
throw std::out_of_range("Iterator out of range!");
}
if (size_ >= capacity_) {
realoc();
}
if (index == 0) {
push_front(std::move(e));
}
else {
for (size_t i = size_; i >= index; --i) {
*(arr_ + i + 1) = std::move(*(arr_ + i));
}
arr_[index] = std::move(e);
++size_;
}
return Iterator{ arr_ + index };
}
Iterator rbegin() const {
return end() - 1;
}
Iterator rend() const {
return begin() - 1;
}
Iterator erase(Iterator beginIt, Iterator endIt) {
size_t beginIndex = beginIt - begin();
size_t endIndex = endIt - begin();
if (beginIndex > endIndex || beginIndex < 0 || endIndex > size_ || beginIndex > size_) {
throw std::out_of_range("Iterators out of range!");
}
for (size_t i = beginIndex; i < endIndex; ++i) {
arr_[i] = std::move(arr_[endIndex - beginIndex + i]);
}
size_ -= (endIndex - beginIndex);
return Iterator{ arr_ + beginIndex };
}
void rotate() {
for (size_t beginIndex = 0, endIndex = size_ - 1; beginIndex < endIndex; ++beginIndex, --endIndex) {
std::swap(arr_[beginIndex], arr_[endIndex]);
}
return;
}
void rotate(Iterator beginIt, Iterator endIt) {
size_t beginIndex = beginIt - Iterator(arr_);
size_t endIndex = (endIt - Iterator(arr_)) - 1;
if (beginIndex > endIndex || beginIndex < 0 || endIndex > size_ || beginIndex > size_) {
throw std::out_of_range("Iterators out of range!");
}
while (beginIndex < endIndex) {
std::swap(arr_[beginIndex], arr_[endIndex]);
++beginIndex;
--endIndex;
}
return;
}
T* data() {
return arr_;
}
};
template <typename T>
std::ostream& operator<<(std::ostream& outputStream, const MojVektor<T>& container) {
const size_t size = container.size();
outputStream << "{";
for (size_t i = 0; i < size; ++i) {
outputStream << container[i];
if (i + 1 < size) {
outputStream << ", ";
}
}
outputStream << "}";
return outputStream;
}
template <typename T>
class MojVektor<T>::Iterator : public std::iterator<std::random_access_iterator_tag, T> {
private:
T* ptr_;
public:
Iterator() : ptr_{ nullptr } {};
Iterator(T* ptr) : ptr_{ ptr } {};
Iterator(T& e) : ptr_{ &e } {};
Iterator(const Iterator& second) : ptr_{ second.ptr_ } {};
Iterator(Iterator&& second) : ptr_(std::move(second.ptr_)) {
second.ptr_ = nullptr;
return;
}
Iterator& operator=(const Iterator& second) {
ptr_ = second.ptr_;
return *this;
}
Iterator& operator=(Iterator&& second) {
ptr_ = std::move(second.ptr_);
second.ptr_ = nullptr;
return *this;
}
T& operator*() {
return *ptr_;
}
Iterator& operator++() {
++ptr_;
return *this;
}
Iterator operator++(int) {
Iterator returnValue{ ptr_ };
++ptr_;
return returnValue;
}
Iterator& operator--() {
--ptr_;
return *this;
}
Iterator operator--(int) {
Iterator returnValue{ ptr_ };
--ptr_;
return returnValue;
}
Iterator& operator+=(size_t n) {
ptr_ += n;
return *this;
}
Iterator& operator-=(size_t n) {
ptr_ -= n;
return *this;
}
Iterator operator+(size_t n) const {
return Iterator(ptr_ + n);
}
Iterator operator-(size_t n) const {
return Iterator(ptr_ - n);
}
T* operator->() {
return ptr_;
}
size_t operator-(const Iterator& second) const {
return ptr_ - second.ptr_;
}
T& operator[](size_t index) const {
return *(ptr_ + index);
}
bool operator==(const Iterator& second) const {
return ptr_ == second.ptr_;
}
bool operator!=(const Iterator& second) const {
return !(this->operator==(second));
}
bool operator<(const Iterator& second) const {
return ptr_ < second.ptr_;
}
bool operator>(const Iterator& second) const {
return ptr_ > second.ptr_;
}
bool operator<=(const Iterator& second) const {
return ptr_ <= second.ptr_;
}
bool operator>=(const Iterator& second) const {
return ptr_ >= second.ptr_;
}
};
主.cpp
#include <iostream>
#include "MojVektor.hpp"
#include <algorithm>
int main() {
MojVektor<int> a{1, 2, 3};
MojVektor<int> b;
std::copy(a.begin(), a.end(), b.begin());
std::cout << a << std::endl;
std::cout << b << std::endl;
return 0;
}
我尝试手动设置 iterator_tag、value_type 等,使用 using、using 和继承、typedef 和 typedef 和继承。我还查看了之前提出的一些问题,但它们与列表和插入器相关,也在答案中添加了我的代码中已经存在的继承。
主要是两个问题:
std::iterator
类已被弃用,因此在这里建立依赖关系不是一个好主意。Iterator
类缺少必要的类型别名。更正这两项后,您的代码将可以编译:
template <typename T>
class MojVektor<T>::Iterator
{
private:
T* ptr_;
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T*;
using reference = T&;
// ....
};