2014-03-12 26 views
0

我想要一個機制在編譯時確定迭代器是否反向。確定一個(C++)迭代器是否反向

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。我不/不能改變這種設計,我只是想用一種更優雅的方式(如果有的話)在內部處理它。我再次重申這是一個虛擬的例子。

+0

什麼'reverse_iterator'? http://www.cplusplus.com/reference/iterator/reverse_iterator/ – Brian

+0

@GIJoe他知道*什麼是*;他想知道,給定一個迭代器,*是否*是。 (我可能誤解了你的評論,雖然 – WhozCraig

+0

@WhozCraig:我想這就是我的觀點......他已經知道他需要一個reverse_iterator,如果你傳遞一個reverse_iterator開始,我不會看到其他任何東西都會被接受的可能性 – Brian

回答

5
#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> 
{ }; 

你也可以針對反向迭代器的任何用戶定義的迭代器專門化trait。

+0

這是如此完美,它讓我想知道爲什麼它不在標準庫中。thnx男人我很高興我終於問到了這個問題 –

+0

因爲沒有人需要它,你的函數應該是'points_to_last_element(Cont const&container,It iter,It end)'並檢查'iter == end',它是否是一個反向迭代器應該沒關係 –

+0

我想如果我結束了,根本沒有必要。如何從迭代器'It it''和容器'Cont cont'的調用者函數獲取'end'迭代器?它是'開始()'或'rbegin()'(我發佈這個作爲一個評論,而不是混亂的問題) –

0

一個簡單的方法。它很容易使用,並且可以確定某個東西是否是反向迭代器,並且可以根據需要區分常量反向迭代器。

#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; 

} 

輸出: