how to detect if a type is an iterator or const_iterator

前端 未结 5 464
北荒
北荒 2020-12-31 07:24

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 ite

相关标签:
5条回答
  • 2020-12-31 07:43

    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;
    };
    
    0 讨论(0)
  • 2020-12-31 07:45

    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.

    0 讨论(0)
  • 2020-12-31 07:57

    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 讨论(0)
  • 2020-12-31 07:59

    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;
    }
    
    0 讨论(0)
  • 2020-12-31 08:02

    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

    0 讨论(0)
提交回复
热议问题