检查容器类型

时间:2016-06-26 14:54:05

标签: c++ list vector typeid typeinfo

如何检查容器类型?即

template <class Container1>
void func (Container1 &cont_1)
{
  if (cont_1 is list container)
    //do stuff
  if (cont_1 is vector container)    
    //do other stuff
}

我唯一有两种可能性就是列表和向量。请注意,我不知道list / vector中的值类型,即vector<char>vector<int>等等,因此我只想获取获取向量或列表的信息。 我遇到了typeidtype info,但没有真正完成它。

3 个答案:

答案 0 :(得分:3)

您可以使用函数重载来实现:

template<typename T>
void func(std::vector<T>& vec)
{
    //Do something with vector
}

template<typename T>
void func(std::list<T>& list)
{
    //Do something with list
}

或使用typeid,这可能不太理想,因为任何一种情况下的代码都必须可以同时编译std::vectorstd::list,因为模板在编​​译时是已知的,即使分支可能不在std::list上执行,编译器也不知道这一点,因此编译失败,尝试对std::vector进行操作std::list

template<template<typename, typename> class C, typename T, typename Alloc>
void func(C<T, Alloc>& container)
{
    if (typeid(container).hash_code() == typeid(std::vector<T, Alloc>&).hash_code())
        ; //Do something with vector
    else if (typeid(container).hash_code() == typeid(std::list<T, Alloc>&).hash_code())
        ; //Do something with list
}

答案 1 :(得分:0)

您可以使用可变参数模板编写一些测试:

#include <vector>

// is_vector
// =========

namespace Detail {
    template<typename T>
    struct is_vector_type : std::false_type
    {};

    template<typename ... Types>
    struct is_vector_type<std::vector<Types...>>  : std::true_type
    {};
}

template<typename T>
struct is_vector_type : Detail::is_vector_type<typename std::decay<T>::type>
{};

template<typename T>
constexpr bool is_vector(T&&) {
    return is_vector_type<T>();
}

// Test
// ====

#include <iostream>

template <class Container>
void func (Container &container)
{
  if (is_vector_type<Container>()) {
    std::cout << "vector\n";
  }
  // or
  if (is_vector(container)) {
    std::cout << "vector\n";
  }
  // ...
}

int main() {
    std::vector<int> v;
    func(v);
    static_assert(is_vector(v), "");
}

答案 2 :(得分:0)

重载的方法当然更好,但是为了完整性,还有另一个使用sfinae机制。在c ++ 11之前,示例代码看起来像:

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

template <bool V, class T = void>
struct enable_if { };

template <class T>
struct enable_if<true, T> {
   typedef T type;
};

struct true_type {
   static const bool value = true;
};

struct false_type {
   static const bool value = false;
};

template <class T>
struct is_list: false_type {};

template <class T>
struct is_list<typename std::list<T> >: true_type { };

template <class T>
struct is_vector: false_type { };

template <class T>
struct is_vector<typename std::vector<T> >: true_type { };

template <class C>
typename enable_if<is_vector<C>::value>::type func(C &c) {
   // c is a vector here
   std::cout << "This is a vector" << std::endl;
}

template <class C>
typename enable_if<is_list<C>::value>::type func(C &c) {
   // c is a list here
   std::cout << "This is a list" << std::endl;
}

int main() {
   std::vector<int> v;
   func(v);
   std::list<int> l;
   func(l);
}

在c ++ 11中,它会变得更简单:

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

template <class T>
struct is_list: std::false_type {};

template <class T>
struct is_list<typename std::list<T>>: std::true_type { };

template <class T>
struct is_vector: std::false_type { };

template <class T>
struct is_vector<typename std::vector<T>>: std::true_type { };

template <class C>
typename std::enable_if<is_vector<C>::value>::type func(C &c) {
   // c is a vector here
   std::cout << "This is a vector" << std::endl;
}

template <class C>
typename std::enable_if<is_list<C>::value>::type func(C &c) {
   // c is a list here
   std::cout << "This is a list" << std::endl;
}

int main() {
   std::vector<int> v;
   func(v);
   std::list<int> l;
   func(l);
}