簡體   English   中英

如何將迭代器限制為前向迭代器?

[英]How to restrict an iterator to being a forward iterator?

我有一個需要多次枚舉迭代器的函數,但是根據MSDN“一旦你增加了輸入迭代器的任何副本,其他副本都不能安全地進行比較,解除引用或增加。”

因此,為了簡化操作,我不想為復制數據和枚舉副本的非正向迭代器創建單獨的實現,而是希望將我的方法限制為只接收前向迭代器,並靜態拒絕輸入迭代器。

現在我有類似的東西:

template<typename It, typename TCallback /*signature: bool(value_type)*/>
bool EnumerateTwice(const It &begin, const It &end, TCallback callback)
{
    for (It it = begin; it != end; ++it)
        if (!callback(*it))
            return false;
    for (It it = begin; it != end; ++it)
        if (!callback(*it))
            return false;
    return true;
}

但沒有什么限制It成為一個前進的迭代器。

如何將限制放在模板化函數上? (C ++ 03)

您可以使用SFINAE並通過以下方式替換bool

typename enable_if<
   is_same<typename std::iterator_traits<It>::iterator_category,
           std::forward_iterator_tag>::value,
   bool>::type

如果您不想從Boost或TR1中提取is_sameenable_if則可能需要自己定義:

template <typename A, typename B>
struct is_same { static const bool value = false; };

template <typename T>
struct is_same<T, T> { static const bool value = true; };

template <bool, typename> struct enable_if { };
template <typename T> struct enable_if<true, T> { typedef T type; };

沒有經過測試,但您可以嘗試以下方面:

template<typename It, typename TCallback /*signature: bool(value_type)*/>
bool EnumerateTwice_Interal(const It &begin, const It &end, TCallback callback, 
      std::forward_iterator_tag)
{
     //do your things
}

template<typename It, typename TCallback /*signature: bool(value_type)*/>
bool EnumerateTwice(const It &begin, const It &end, TCallback callback)
{
    EnumerateTwice_Internal(begin, end, callback,
        typename std::iterator_traits<It>::iterator_category());
}

你可以使用std::enable_if來做到這一點:

#include <iterator>
#include <type_traits>
#include <utility>

template <typename It, typename TCallback>
typename std::enable_if<std::is_base_of<std::forward_iterator_tag,
                        typename std::iterator_traits<It>::iterator_category>::value,
                    bool>::type
EnumerateTwice(It begin, It end, TCallback) {
    ...
}

這使用了C ++ 11中的類,但所有這些都可以在C ++ 03中完成。

為了擴展羅德里戈的答案 - 我找到了這個解決方案,並認為值得一提:

struct True { unsigned char _[2]; operator bool() const { return true; } };
char is_forward_iterator(std::input_iterator_tag const *) { return 0; }
True is_forward_iterator(std::forward_iterator_tag const *) { return True(); }

現在,如果你想在某個功能中檢查它,你可以說:

if (is_forward_iterator(static_cast<iterator_traits<It>::iterator_category*>(0)))
{
    ...
}

如果你想在模板中檢查它,你可以檢查:

sizeof(
  is_forward_iterator(static_cast<iterator_traits<It>::iterator_category*>(0))
) > 1

這種方法的主要優點是它避免了聲明模板(例如,為了更好的編譯速度)。

暫無
暫無

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

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