【问题标题】: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,但并没有真正完成。

【问题讨论】:

    标签: c++ list vector typeid typeinfo


    【解决方案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] 在向量的条件部分他会导致编译错误...
      猜你喜欢
      • 1970-01-01
      • 2010-12-15
      • 1970-01-01
      • 2018-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多