开发者

how to detect if a type is an iterator or const_iterator

I'm wondering, if there is a way to check at compile time whether a type T of some iterator type is a const_iterator, or not. Is there some difference in 开发者_如何转开发the types that iterators define (value_type, pointer, ...) between iterators and const iterators?

I would like to achieve something like this:

typedef std::vector<int> T;

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


C++03 Solution:

As none of the answer seems correct, here is my attempt which is working with 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;
};

Example:

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

Output:

0
1

Online Demo : http://ideone.com/TFYcW


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


One method that works at least on gcc is via the reference 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;
};

You can verify that it works by using

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());
}

With a sufficiently high optimization level, the last two functions should be reduced to return false; and return true;, respectively. At least they do for me.


With C++11, the new standard header <type_traits> provides std::is_const<T>, so Nawaz's solution can be simplified:

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


This is a bit hacky because you have to pass T itself but it works (template specialization, 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
    };
};

Use like this:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜