在编译时确定类型是否为 STL 容器

新手上路,请多包涵

我想编写一个模板,在编译时确定一个类型是否是 stl 容器。

我有以下代码:

 struct is_cont{};
struct not_cont{};

template <typename T>
struct is_cont { typedef not_cont result_t; };

但我不确定如何为 std::vector<T,Alloc>, deque<T,Alloc>, set<T,Alloc,Comp> 等创建必要的专业化……

原文由 Xander Tulip 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 490
2 个回答

首先,您定义您的主模板,该模板将有一个在默认情况下为 false 的成员:

 template <typename T>
struct is_cont {
  static const bool value = false;
};

然后,您将为您的容器类型定义部分特化,其值为 true:

 template <typename T,typename Alloc>
struct is_cont<std::vector<T,Alloc> > {
  static const bool value = true;
};

然后对于您要检查的类型 X,使用它

if (is_cont<X>::value) { ... }

原文由 Vaughn Cato 发布,翻译遵循 CC BY-SA 3.0 许可协议

注意: 以下代码取自 @Kerrek SB 编写的一个名为 pretty-print 的优秀实用程序(stackoverflow 上的一个 主题)。

免责声明:我不知道是否可以在未经原作者许可的情况下复制并粘贴此代码。 @Kerrek,如果您有任何问题,请告诉我。 :-)


您可以使用此类模板:

   template<typename T>
  struct is_container : std::integral_constant<bool, has_const_iterator<T>::value && has_begin_end<T>::beg_value && has_begin_end<T>::end_value>
  { };

用法:

  std::cout << is_container<std::vector<int>>::value << std::endl; //true
 std::cout << is_container<std::list<int>>::value << std::endl;   //true
 std::cout << is_container<std::map<int>>::value << std::endl;    //true
 std::cout << is_container<std::set<int>>::value << std::endl;    //true
 std::cout << is_container<int>::value << std::endl;              //false

请注意 is_container 需要以下帮助类模板:

 template<typename T>
struct has_const_iterator
{
private:
    typedef char                      yes;
    typedef struct { char array[2]; } no;

    template<typename C> static yes test(typename C::const_iterator*);
    template<typename C> static no  test(...);
public:
    static const bool value = sizeof(test<T>(0)) == sizeof(yes);
    typedef T type;
};

template <typename T>
struct has_begin_end
{
    template<typename C> static char (&f(typename std::enable_if<
      std::is_same<decltype(static_cast<typename C::const_iterator (C::*)() const>(&C::begin)),
      typename C::const_iterator(C::*)() const>::value, void>::type*))[1];

    template<typename C> static char (&f(...))[2];

    template<typename C> static char (&g(typename std::enable_if<
      std::is_same<decltype(static_cast<typename C::const_iterator (C::*)() const>(&C::end)),
      typename C::const_iterator(C::*)() const>::value, void>::type*))[1];

    template<typename C> static char (&g(...))[2];

    static bool const beg_value = sizeof(f<T>(0)) == 1;
    static bool const end_value = sizeof(g<T>(0)) == 1;
};

原文由 Nawaz 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题