检查模板参数是否为 std::vector<T>::iterator

问题描述 投票:0回答:5

如何检查模板参数是否为

std::vector<T>::iterator

对于 void 类型,我们有 std::is_void。有类似的东西吗

std::vector<T>::iterator

c++ templates vector iterator
5个回答
7
投票

你可以为此创建一个特质:

#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");
}

[现场演示]


4
投票

另一种解决方案也使用 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;
}

现场演示


3
投票

更好地使用 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");
}

演示


2
投票

您可以为此编写一个特征:

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

在这里,我获取 *t 的衰退类型来制作

vector<type>::iterator
并检查其与
T
是否相等。它可以工作,但
vector<bool>
无论如何都不是真正的向量。

演示


0
投票

可以实现自定义类型特征

is_vector_iterator
,如果类型
T
std::vector<U>::iterator
相同,则其计算结果为 true。

基本思想是创建一个辅助类型特征,它接受两种不同的类型作为模板参数。它是部分特化的,用于第二个参数与

std::vector <U>::iterator
相同的情况,其中类型
U
是迭代器的
value_type
。因此,助手仅专门针对
T
类型。如果上述类型不是
std::vector
容器迭代器,则选择第一个类;否则,选择第二个。

示例:

namespace detail {
    template <typename, typename>
    struct is_vector_iterator
     : public std::false_type {};
    
    template <typename T>
    struct is_vector_iterator<T, typename std::vector<typename std::iterator_traits<T>::value_type>::iterator>
     : public std::true_type {};
}

template <typename T>
struct is_vector_iterator
 : public detail::is_vector_iterator<T, T> {};

template <typename T>
inline constexpr bool is_vector_iterator_v = is_vector_iterator<T>::value;
© www.soinside.com 2019 - 2024. All rights reserved.