簡體   English   中英

如何創建可以接受滿足 std::forward_iterator 的任何類型的模板類<T>在構造函數中?

[英]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>::iteratorstd::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_vforward_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>::iteratorstd::deque<int>::iterator之間沒有共同的類型供您作為CircularIterator<int>的數據成員。

在內存受限的環境中,為什么還要首先混合std::arraystd::vectorstd::deque 這些是更大的模板。 如果您使用的唯一容器是std::vector ,那么在CircularIterator<int>中持有std::vector<int>::iterator s 還是int *有什么關系?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM