2011-03-24 39 views
12

我想知道,如果有一種方法可以在編譯時檢查一些迭代器類型的T是否是const_iterator,或者不是。迭代器和常量迭代器之間的迭代器定義的類型(value_type,pointer,...)有區別嗎?如何檢測類型是否是迭代器或const_iterator

我想實現這樣的事情:

的作品至少在GCC
typedef std::vector<int> T; 

is_const_iterator<T::iterator>::value  // is false 
is_const_iterator<T::const_iterator>::value // is true 

回答

20

C++ 03解決方案:

由於沒有一個答案似乎是正確的,這裏是我正在與GCC合作的嘗試:

template<typename T> 
struct is_const_pointer { static const bool value = false; }; 

template<typename T> 
struct is_const_pointer<const T*> { static const bool value = true; }; 

template <typename TIterator> 
struct is_const_iterator 
{ 
    typedef typename std::iterator_traits<TIterator>::pointer pointer; 
    static const bool value = is_const_pointer<pointer>::value; 
}; 

實施例:

int main() 
{ 
    typedef std::vector<int>::iterator it_type; 
    typedef std::vector<int>::const_iterator const_it_type; 

    std::cout << (is_const_iterator<it_type>::value) << std::endl; 
    std::cout << (is_const_iterator<const_it_type>::value) << std::endl; 
} 

輸出:

0 
1 

在線演示:http://ideone.com/TFYcW

+0

最近是否只是我或者社區上漲缺乏? :(+1你說它的工作,它看起來不錯 – 2011-03-24 18:36:04

+3

我選擇了你的答案,因爲你的解決方案使用std :: iterator_traits <>類 – 2011-03-24 19:28:50

+2

當'std :: iterator_traits :: pointer'是一個代理類的類型,但是如果有解決方案的話,就必須使用一些非常令人討厭的SFINAE – aschepler 2011-03-24 20:18:12

5

一種方法是通過參考的typedef:

struct true_type { }; 
struct false_type { }; 

template<typename T> 
struct is_const_reference 
{ 
    typedef false_type type; 
}; 

template<typename T> 
struct is_const_reference<T const &> 
{ 
    typedef true_type type; 
}; 

template<typename T> 
struct is_const_iterator 
{ 
    typedef typename is_const_reference< 
     typename std::iterator_traits<T>::reference>::type type; 
}; 

您可以驗證它的工作方式使用

inline bool test_internal(true_type) 
{ 
    return true; 
} 

inline bool test_internal(false_type) 
{ 
    return false; 
} 

template<typename T> 
bool test(T const &) 
{ 
    return test_internal(typename is_const_iterator<T>::type()); 
} 

bool this_should_return_false(void) 
{ 
    std::list<int> l; 
    return test(l.begin()); 
} 

bool this_should_return_true(void) 
{ 
    std::list<int> const l; 
    return test(l.begin()); 
} 

隨着足夠高h優化級別,最後兩個函數應該分別減少到return false;return true;。至少他們爲我做。

+0

你有沒有測試它? 'iterator'類型是否具有'reference'類型?發佈一個工作代碼給ideone! – Nawaz 2011-03-24 19:32:12

+0

是的,我查看了反彙編程序的輸出,並且看到測試函數確實將常量返回到所需的結果。我在這裏使用類型來表示true和false,原則上你也可以使用'static'' const'成員並獲得相同的效果。 – 2011-03-25 07:08:11

+0

我指的是這個語法'typename T :: reference'。當你的語法中'l.begin()'的類型可以是'iterator'或'const_iterator'這個實際上是'T'的時候,你怎麼能寫出這個。所以我的問題是:'iterator :: reference'如何工作?你測試過了嗎?請在www.ideone.com上發佈工作代碼。 – Nawaz 2011-03-25 07:22:24

0

這是一個有點哈克,因爲你必須通過T本身,而是它的工作原理(模板特,G ++ 4.4.5):

template<typename T, typename S> 
struct is_const_iterator { 
    enum { 
     value = false 
    }; 
}; 

template<typename T> 
struct is_const_iterator<T, typename T::const_iterator> { 
    enum { 
     value = true 
    }; 
}; 

使用這樣的:

typedef std::vector<int> T; 
is_const_iterator<T, T::iterator>::value   //is false 
is_const_iterator<T, T::const_iterator>::value  //is true 
+1

它還要求您傳遞容器類型。所以不是一個解決方案,在我看來! – Nawaz 2011-03-24 18:20:58

3

用C++ 11,新的標準頭<type_traits>提供std::is_const<T>, 所以納瓦茲的溶液可以被簡化:

template<typename Iterator> 
struct is_const_iterator 
{ 
    typedef typename std::iterator_traits<Iterator>::pointer pointer; 
    static const bool value = 
     std::is_const<typename std::remove_pointer<pointer>::type>::value; 
}; 
4

C++ 11

template<class IT, class T=decltype(*std::declval<IT>())>  
constexpr bool 
is_const_iterator() { 
     return ! std::is_assignable < 
       decltype(*std::declval<IT>()), 
       T 
     >::value; 
} 
+1

這是const_iterator的常量的核心 - 您不能指定給這個東西可能是唯一的答案,適用於奇怪的球,如向量(當然,它不會檢查它是否是迭代器,或者是deref但是OP認爲它是某種迭代器。但是把它叫做「is_const_iterator」,它應該檢查const和ness-ness ......) – tony 2015-01-29 18:19:53

+0

如果迭代器表示的類型T有賦值操作符被刪除,我認爲這不會正確工作。 – 2016-12-02 14:08:33

相關問題