1

在我的工作中,我们做了很多结对编程,我写了一个函数,它只接受单一类型的容器或其衍生物,但我的同事担心它会通过代码审查,因为它看起来非常丑陋,并说必须做一个更好的方法:

这是签名,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 并启用该函数。我还使用了 std::remove_pointer 因为我需要知道指针的“类型”(容器很可能有指针)。

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

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

任何替代的想法,还是像现在这样好吗?提前致谢。

4

1 回答 1

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 容器”,但是您想定义它。要正确地做到这一点,您需要一个 trait 来测试begin()end()size()成员以及容器要求指定的所有嵌套类型iteratorvalue_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 */>
{ };
于 2012-07-13T19:26:30.223 回答