2011-03-24 38 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

相关问题