检查容器类型

Posted

技术标签:

【中文标题】检查容器类型【英文标题】:Check for container type 【发布时间】:2016-06-26 14:54:04 【问题描述】:

如何检查容器的类型? IE。

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&lt;char&gt;vector&lt;int&gt;等是可能的,因此我只想获取获取向量或列表的信息。 我遇到了typeidtype info,但并没有真正完成。

【问题讨论】:

【参考方案1】:

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

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::list 应用 std::vector 操作。

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

【讨论】:

有没有办法不使用重载?如果我有一个完全一样的功能,除了这个if-statement,不拥有两次不是很好吗? @SemtexB 大概是if 中的东西做了一些事情。所以把它放在重载的函数中。 @SemtexB 您还可以将重复代码提取到其他函数中,并在重载或反向中调用它并创建 func_if 这只会做有条件的东西并从您原来的 func 调用它 是的,添加评论后才意识到。效果很好,谢谢! @SemtexB 这是typeid 的解决方案:)【参考方案2】:

重载的方法当然更好,但为了完整性,还有另一种使用 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);

【讨论】:

【参考方案3】:

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

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

【讨论】:

这种方式使用例如cont_1[i] 在向量的条件部分他会导致编译错误...

以上是关于检查容器类型的主要内容,如果未能解决你的问题,请参考以下文章

为啥容器类型没有类型类?

函数式编程:容器类型值类型

泛星容器类ArrayList

继承类类型的c ++容器

从基类函数派生的类容器

Qt中容器类应该如何存储对象