Tôi cảm thấy rằng không có câu trả lời nào ở đây giải thích lý do tại sao tôi thích các trình vòng lặp như một khái niệm chung về việc lập chỉ mục vào các thùng chứa. Lưu ý rằng hầu hết trải nghiệm của tôi khi sử dụng các trình vòng lặp không thực sự đến từ C ++ mà từ các ngôn ngữ lập trình cấp cao hơn như Python.
Giao diện iterator áp đặt ít yêu cầu hơn đối với người tiêu dùng về chức năng của bạn, cho phép người tiêu dùng làm nhiều hơn với nó.
Nếu tất cả bạn cần là để có thể chuyển tiếp-lặp, các nhà phát triển không giới hạn việc sử dụng container lập chỉ mục - họ có thể sử dụng bất kỳ lớp thực hiện operator++(T&)
, operator*(T)
và operator!=(const &T, const &T)
.
#include <iostream>
template <class InputIterator>
void printAll(InputIterator& begin, InputIterator& end)
{
for (auto current = begin; current != end; ++current) {
std::cout << *current << "\n";
}
}
// elsewhere...
printAll(myVector.begin(), myVector.end());
Thuật toán của bạn hoạt động cho trường hợp bạn cần - lặp lại qua một vectơ - nhưng nó cũng có thể hữu ích cho các ứng dụng mà bạn không nhất thiết phải dự đoán:
#include <random>
class RandomIterator
{
private:
std::mt19937 random;
std::uint_fast32_t current;
std::uint_fast32_t floor;
std::uint_fast32_t ceil;
public:
RandomIterator(
std::uint_fast32_t floor = 0,
std::uint_fast32_t ceil = UINT_FAST32_MAX,
std::uint_fast32_t seed = std::mt19937::default_seed
) :
floor(floor),
ceil(ceil)
{
random.seed(seed);
++(*this);
}
RandomIterator& operator++()
{
current = floor + (random() % (ceil - floor));
}
std::uint_fast32_t operator*() const
{
return current;
}
bool operator!=(const RandomIterator &that) const
{
return current != that.current;
}
};
int main()
{
// roll a 1d6 until we get a 6 and print the results
RandomIterator firstRandom(1, 7, std::random_device()());
RandomIterator secondRandom(6, 7);
printAll(firstRandom, secondRandom);
return 0;
}
Cố gắng thực hiện một toán tử ngoặc vuông làm một cái gì đó tương tự như trình vòng lặp này sẽ bị hạn chế, trong khi việc thực hiện vòng lặp tương đối đơn giản. Toán tử dấu ngoặc vuông cũng đưa ra hàm ý về các khả năng của lớp của bạn - rằng bạn có thể lập chỉ mục cho bất kỳ điểm tùy ý nào - có thể khó thực hiện hoặc không hiệu quả.
Lặp đi lặp lại cũng cho vay để trang trí . Mọi người có thể viết các trình vòng lặp lấy một trình vòng lặp trong hàm tạo của chúng và mở rộng chức năng của nó:
template<class InputIterator, typename T>
class FilterIterator
{
private:
InputIterator internalIterator;
public:
FilterIterator(const InputIterator &iterator):
internalIterator(iterator)
{
}
virtual bool condition(T) = 0;
FilterIterator<InputIterator, T>& operator++()
{
do {
++(internalIterator);
} while (!condition(*internalIterator));
return *this;
}
T operator*()
{
// Needed for the first result
if (!condition(*internalIterator))
++(*this);
return *internalIterator;
}
virtual bool operator!=(const FilterIterator& that) const
{
return internalIterator != that.internalIterator;
}
};
template <class InputIterator>
class EvenIterator : public FilterIterator<InputIterator, std::uint_fast32_t>
{
public:
EvenIterator(const InputIterator &internalIterator) :
FilterIterator<InputIterator, std::uint_fast32_t>(internalIterator)
{
}
bool condition(std::uint_fast32_t n)
{
return !(n % 2);
}
};
int main()
{
// Rolls a d20 until a 20 is rolled and discards odd rolls
EvenIterator<RandomIterator> firstRandom(RandomIterator(1, 21, std::random_device()()));
EvenIterator<RandomIterator> secondRandom(RandomIterator(20, 21));
printAll(firstRandom, secondRandom);
return 0;
}
Mặc dù những đồ chơi này có vẻ trần tục, nhưng không khó để tưởng tượng bằng cách sử dụng các trình lặp và trang trí lặp để làm những việc mạnh mẽ với giao diện đơn giản - trang trí một trình lặp kết quả cơ sở dữ liệu chỉ với một trình vòng lặp xây dựng một đối tượng mô hình từ một kết quả duy nhất, ví dụ . Các mẫu này cho phép lặp lại hiệu quả bộ nhớ của các bộ vô hạn và, với bộ lọc như bộ tôi đã viết ở trên, có khả năng đánh giá kết quả lười biếng.
Một phần sức mạnh của các mẫu C ++ là giao diện lặp của bạn, khi được áp dụng cho các mảng C có độ dài cố định, phân rã thành số học con trỏ đơn giản và hiệu quả , làm cho nó trở thành một sự trừu tượng hóa chi phí thực sự.
some_iterator++
sang++some_iterator
. Tăng sau tạo ra một trình vòng lặp tạm thời không cần thiết.