确定 (c++) 迭代器是不是是反向的

Posted

技术标签:

【中文标题】确定 (c++) 迭代器是不是是反向的【英文标题】:Determine if a (c++) iterator is reverse确定 (c++) 迭代器是否是反向的 【发布时间】:2014-03-12 18:29:55 【问题描述】:

我想要一种机制来在编译时确定迭代器是否是反向的。

Iterator traits 只能帮助处理迭代器类型的 类别,而我需要的是:

template<typename IterType>
struct IsReverseIterator

    enum  Yes = /* Implementation of the mechanism */ ;

我有一个解决方案,但有一个小缺点,但也必须提供容器类型:

typedef char     TrueT;
typedef struct  TrueT _[2];  FalseT;

template<typename Cont> TrueT  IsReverseIterator(typename Cont::const_reverse_iterator);    
template<typename Cont> FalseT IsReverseIterator(...);

它显然使用了 SFINAE,可以这样使用:

std::vector<int> v;

std::cout << (sizeof(IsReverseIterator<std::vector<int>>(v.begin())) ==  sizeof(TrueT)) << std::endl;
std::cout << (sizeof(IsReverseIterator<std::vector<int>>(v.rbegin())) ==  sizeof(TrueT)) << std::endl;    

有什么想法吗?

编辑

为了解释我正在搜索的内容,例如下面的代码

template<typename Cont, typename It>
bool points_to_last_element(Cont const &container, It iter)

    return iter == container.rend(); 
    // here I would like to dispatch to 2 implementations
    // one for reverse iterators and one for forward where this would happen
    // return iter == container.end();

这是一个虚拟的例子,请不要被我已经处理过的代码或者我可能有两个重载,一个采用Cont::reverse_iterator 和一个采用Cont::iterator 的事实抓住。我不会/不能改变那个设计,我只是在尝试一种更优雅的方式(如果有的话)在内部处理它。我再说一遍,那是个假例子。

【问题讨论】:

reverse_iterator 怎么样? cplusplus.com/reference/iterator/reverse_iterator @GIJoe 他知道是什么;他想知道,给定一个迭代器,是否是一个。 (不过我可能误解了你的评论。 @WhozCraig:我想这就是我的意思.. 他已经知道他需要一个 reverse_iterator。如果您传递一个 reverse_iterator 以开始,我看不出有可能接受其他任何东西 你为什么在乎?你能检查.base()(看看它是否返回一个迭代器)吗?你所说的“是一个反向迭代器”到底是什么意思?我可以编写一个适用于所有意图的类,但std::reverse_iterator 不会返回。如何定义实现是好的? 【参考方案1】:
#include <iterator>
#include <type_traits>

template<typename Iter>
struct is_reverse_iterator : std::false_type  ;

template<typename Iter>
struct is_reverse_iterator<std::reverse_iterator<Iter>>
: std::integral_constant<bool, !is_reverse_iterator<Iter>::value>
 ;

您还可以为任何用户定义的作为反向迭代器的迭代器专门化特征。

【讨论】:

太完美了,我想知道为什么它不在标准库中。我很高兴我终于问了这个问题。 因为没有人需要,所以你的函数应该是points_to_last_element(Cont const &amp;container, It iter, It end)并检查iter == end,不管是不是反向迭代器 我想如果我已经结束了,那根本就没有必要了。如何从迭代器It iter 和容器Cont cont 的调用函数中获取end 迭代器?是begin() 还是rbegin()(我将其作为评论发布,以免混淆问题) 你是如何获得iter的?哪里来的就是你知道如何获取过去的结束迭代器的地方 那是(过去是 - 现在不再是)问题我无法在那里添加代码,我只能是该代码的用户/客户【参考方案2】:

一个简单的方法。它易于使用,并且可以确定某个东西是否是反向迭代器,并且可以根据需要区分 const 反向迭代器。

#include <iostream>

template<typename Container, typename T>
using IsRegRevIter = std::is_same<T,typename Container::reverse_iterator>;

template<typename Container, typename T>
using IsConstRevIter = std::is_same<T,typename Container::const_reverse_iterator>;

template<typename Container, typename T>
struct IsRevIter

     const static bool value = IsRegRevIter<Container,T>::value
          || IsConstRevIter<Container,T>::value;
;

int main()

     using Container = std::list<int>;
     Container myList = 1,2,3,4,5,6;

     auto RI = myList.rbegin();
     auto I = myList.begin();

     std::cout << std::endl << std::boolalpha << IsRevIter<Container,decltype(RI)>::value; //true
     std::cout << std::endl << std::boolalpha << IsRegRevIter<Container,decltype(RI)>::value; //true
     std::cout << std::endl << std::boolalpha << IsConstRevIter<Container,decltype(RI)>::value; //false (it is not const).
     std::cout << std::endl << std::boolalpha << IsRevIter<Container,decltype(I)>::value; //false

return 0;


输出:假 真 假 假

【讨论】:

以上是关于确定 (c++) 迭代器是不是是反向的的主要内容,如果未能解决你的问题,请参考以下文章

C++迭代器 iterator

C++迭代器 iterator

C++ STL list迭代器

容器迭代器

为 std::any_of 等提供反向迭代器是不是有意义?

反向迭代器