[英]How do I create a template class that can accept any type that satisfies std::forward_iterator<T> in the constructor?
我正在制作一個循環迭代器類,其行為類似於前向迭代器,除了它在到達范圍末尾后循環回到開頭。
template <typename T>
struct CircularIterator
{
CircularIterator(T* begin, T* end);
// Omitted overloaded operators
T* mBegin; // Points to beginning of range
T* mIter; // Current item
T* mEnd; // Points to end of range
};
沒有從 STL 迭代器(例如std::vector<int>::iterator>
)到原始指針( T*
)的轉換。 以下代碼編譯時出現錯誤:
std::vector<int> vec{1, 2, 3};
CircularIterator<int> iter(vec.begin(), vec.end());
error: cannot convert ‘__gnu_cxx::__normal_iterator<int*, std::vector<int> >’ to ‘int*’ in initialization
如何在構造函數中創建一個可以接受滿足std::forward_iterator<T>
的任何類型的模板類? 我想避免為每個使用的迭代器類型創建一個新的模板實例(例如,新的CircularIterator
用於std::array<T>::iterator
和std::deque<T>::iterator
。)
任何建議都會被采納。 我肯定在我的模板/概念知識的遠端,並期待任何資源來了解更多信息。 謝謝你。
您可以約束CircularIterator
的模板參數I
必須滿足std::forward_iterator
,例如
#include <iterator>
template <std::forward_iterator I>
struct CircularIterator
{
CircularIterator() = default;
CircularIterator(I begin, I end);
// Omitted overloaded operators
I mBegin; // Points to beginning of range
I mIter; // Current item
I mEnd; // Points to end of range
};
請注意,您需要為CircularIterator
提供默認構造函數,因為std::forward_iterator
需要默認構造函數。
在使用帶有is_base_of_v
和forward_iterator_tag
的 SFINAE 的可能方式:
#include <iterator>
#include <type_traits>
template <class It, class EndIt,
std::enable_if_t<std::is_base_of_v<
std::forward_iterator_tag,
typename std::iterator_traits<It>::iterator_category>,int> = 0>
struct CircularIterator {
CircularIterator(It begin, EndIt end)
: mBegin(begin), mIter(begin), mEnd(end) {}
It mBegin; // Points to beginning of range
It mIter; // Current item
EndIt mEnd; // Points to end of range
};
一個 C++20 選項,實例化可能更少,需要迭代器改為contiguous_iterator
:
#include <concepts>
#include <iterator>
#include <type_traits>
template <class T>
struct CircularIterator {
CircularIterator(std::contiguous_iterator auto begin,
std::contiguous_iterator auto end)
: mBegin(begin != end ? &*begin : nullptr),
mIter(mBegin),
mEnd(std::next(mBegin, std::distance(begin, end))) {}
T* mBegin; // Points to beginning of range
T* mIter; // Current item
T* mEnd; // Points to end of range
};
...並在您的示例中使用:
#include <vector>
int main() {
std::vector<int> vec{1, 2, 3};
CircularIterator<int> iter(vec.begin(), vec.end());
}
你的欲望在直接競爭中
在構造函數中滿足 std::forward_iterator 的任何類型?
避免為每個使用的迭代器類型創建一個新的模板實例
選擇其中之一。 std::vector<int>::iterator
和std::deque<int>::iterator
之間沒有共同的類型供您作為CircularIterator<int>
的數據成員。
在內存受限的環境中,為什么還要首先混合std::array
、 std::vector
和std::deque
? 這些是更大的模板。 如果您使用的唯一容器是std::vector
,那么在CircularIterator<int>
中持有std::vector<int>::iterator
s 還是int *
有什么關系?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.