template type_trait function,接受给定类型和/或派生类型的容器

时间:2012-07-13 19:05:17

标签: c++ templates typetraits

在我的工作中我们做了很多结对编程,并且我编写了一个只接受SINGLE类型或其派生的容器的函数,但是我的同事担心它会失败代码审查,因为它看起来非常丑陋和说有更好的方法:

这里是签名,Fruit类是我为这个帖子重命名为Fruit的基类:

template <class Container>
typename enable_if<is_base_of<Fruit, typename remove_pointer<typename Container::value_type>::type>::value, void>::type
processFruits(container& fruits)
{
    //process the elements and change them if needed. thats why no const
}

它的作用是:返回void并启用函数IF它是一个容器和容器内的类型是Fruit和/或派生的fruit。我还使用了std :: remove_pointer,因为我需要知道指针的“类型”(容器很可能有指针)。

这个编译并按预期工作,但正如我所说,我不知道它是最好的方法,它似乎太冗长,可能会削减代码审查。

编辑:这也接受模板化的类,不必是容器。有没有办法可以限制它只接受STL容器?

任何其他想法或它是否很好? 提前谢谢。

1 个答案:

答案 0 :(得分:1)

阅读时有点可怕。

对于初学者来说,您不需要说enable_if<B, void>就可以说enable_if<B>并使用默认模板参数。

您可以轻松地将其拆分为单独的部分:

template <class T>
  struct is_fruity
  : is_base_of<Fruit, T>
  { };

template <class Container, typename Value = typename Container::value_type>
  struct is_fruit_container
  : is_fruity<typename remove_pointer<Value>::type>>
  { };

template<class Container>
  typename enable_if<is_fruit_container<Container>::value>::type
  processFruits(Container& fruits)
  {
    //process the elements and change them if needed. thats why no const
  }

如果你有一个支持别名模板的编译器,你可以更容易阅读:

template<typename Cond>
  using Require = typename enable_if<Cond::value>::type;

template<class Container>
  Require<is_fruit_container<Container>>
  processFruits(Container& fruits)
  {
    //process the elements and change them if needed. thats why no const
  }
  

这也接受模板化的类,不必是容器。有没有办法可以限制它只接受STL容器?

我不确定“模板化类”是什么意思,它只接受嵌套value_type类型的类型,它是从Fruit派生的类型或指向此类型的指针,它不是不一定要成为模板。要将其限制为“STL容器”,您需要编写一个特征来识别“STL容器”,但是您要定义它。要正确执行此操作,您需要一个测试begin()end()size()成员的特征,以及容器要求iterator指定的所有嵌套类型,value_type等。

template<typename C, typename Chead, typename... Ctail>
struct static_and
{
  static const bool value = C::value && static_and<Chead, Ctail...>::value;
};

template<typename C>
struct static_and<C>
{
  static const bool value = C::value;
};

template<typename C>
struct is_container
: static_and<has_begin<C>, has_end<C>, has_iterator<C>, has_value_type<C> /* etc */>
{ };