简体   繁体   English

检查模板参数是否是std :: vector <T> ::迭代

[英]Check if a template argument is a std::vector<T>::iterator

How to check if a template argument is a std::vector<T>::iterator ? 如何检查模板参数是否是std::vector<T>::iterator

For void type, we have std::is_void. 对于void类型,我们有std :: is_void。 Is there something like that for std::vector<T>::iterator ? 对于std::vector<T>::iterator有类似的东西吗?

You could create a trait for that: 你可以为它创建一个特征:

#include <vector>
#include <list>
#include <type_traits>


template <class T, class = void>
struct is_vector_iterator: std::is_same<T, std::vector<bool>::iterator> { };

template <class T>
struct is_vector_iterator<T, decltype(*std::declval<T>(), std::enable_if_t<!std::is_same<T, std::vector<bool>::iterator>::value>())>: std::is_same<T, typename std::vector<std::decay_t<decltype(*std::declval<T>())>>::iterator> { };

int main() {
    static_assert(is_vector_iterator<std::vector<int>::iterator>::value, "Is not a vector iterator");
    static_assert(is_vector_iterator<std::vector<bool>::iterator>::value, "Is not a vector iterator");
    static_assert(!is_vector_iterator<std::list<int>::iterator>::value, "Is a vector iterator");
    static_assert(!is_vector_iterator<std::list<int>::iterator>::value, "Is a vector iterator");
}

[live demo] [现场演示]

Better using std::iterator_traits I think: 更好地使用std :: iterator_traits我认为:

#include <list>
#include <vector>
#include <iterator>

template <class It, class = void>
struct is_vector_iterator : std::false_type { };

template <class It>
struct is_vector_iterator<It, std::enable_if_t<
                                  std::is_same<
                                      It,
                                      typename std::vector< 
                                          typename std::iterator_traits<It>::value_type
                                      >::iterator
                                  >::value
                         >> : std::true_type { };

int main() {
    static_assert(is_vector_iterator<std::vector<int>::iterator>::value, "Is not a vector iterator");
    static_assert(is_vector_iterator<std::vector<bool>::iterator>::value, "Is not a vector iterator");
    static_assert(!is_vector_iterator<std::list<int>::iterator>::value, "Is a vector iterator");
}

DEMO DEMO

An alternative solution also using std::iterator_traits : 另一种解决方案也使用std :: iterator_traits

#include <iostream>
#include <vector>
#include <list>

template <typename T>
struct is_vector_iterator 
{
    typedef char yes[1];
    typedef char no[2];

    template <typename C>
    static yes& test(
        typename std::enable_if<
            std::is_same<T, typename std::vector<typename C::value_type>::iterator>::value
        >::type*);

    template <typename>
    static no& test(...);

    static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);

};

int main() {
    std::cout << is_vector_iterator<int>::value << std::endl;
    std::cout << is_vector_iterator<int*>::value << std::endl;
    std::cout << is_vector_iterator<std::list<int>::iterator>::value << std::endl;
    std::cout << is_vector_iterator<std::vector<int>::iterator>::value << std::endl;
    return 0;
}

live demo 现场演示

You can write a trait for this: 你可以为此写一个特征:

namespace detail
{

template<typename T> constexpr std::false_type is_vector_iterator(T&&, ...)
{
    return {};
}

template<typename T>
constexpr auto is_vector_iterator(T&& t, void* = nullptr) ->
decltype(std::is_same<typename std::vector<std::decay_t<decltype(*t)>>::iterator, std::decay_t<T>>{})
{
    return {};
}

}

template<typename T>
struct is_vector_iterator : decltype(detail::is_vector_iterator(declval<T>(), 0)) {};

Here I'm getting the decayed type of *t to make vector<type>::iterator and check that for equality with T . 在这里,我得到了衰减类型的* t来生成vector<type>::iterator并检查它是否与T相等。 It works with the exception of vector<bool> which isn't really a vector anyway. 除了vector<bool> ,它无论如何都不是一个矢量。

demo 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM