在A或B的任何容器上重载模板成员函数

Overload template member function over any container of A or B

本文关键字:重载 成员 函数 任何容      更新时间:2023-10-16

我有两个现有的类A和B。我想实现第三个结构C,这样C实现operator(),它将使用不同的实现来获取A的任何容器或的任何容器。使用模板专用化可以做这样的事情吗?

enable_if在很多场景中都非常有用,但在这种情况下,我通常更倾向于使用标记调度。在我看来,代码看起来更干净,行为更可预测,如果你试图错误地使用它,错误消息会更有意义。

struct C
{
    template <class T>
    void operator()(const T& container) const
    {
        operator()(container, Tag<typename T::value_type>());
    }
private:
    template <class V> struct Tag {};
    template <class T>
    void operator()(const T& container, Tag<A>) const
    {
        std::cout << "An";
    }
    template <class T>
    void operator()(const T& container, Tag<B>) const
    {
        std::cout << "Bn";
    }
};
int main()
{
    std::vector<A> a;
    std::list<B> b;
    C c;
    c(a);
    c(b);
}

您可以使用模板模板参数来完成此操作。

假设您的容器有两个参数(内容类型和分配器):

class A {};
class B {};
struct C {
  template <
    template <
      typename,
      typename
    >
    class V
  >
  void operator()(const V<A, std::allocator<A> >& /* ca */) const {
  }
  template <
    template <
      typename,
      typename
    >
    class V
  >
  void operator()(const V<B, std::allocator<B> >& /* cb */) const {
  }
};

这将允许您执行以下操作:

int main() {
  std::vector<A> va;
  std::vector<B> vb;
  std::list<A> la;
  std::list<B> lb;
  C c;
  c(va);
  c(la);
  c(vb);
  c(lb);
}

使用std::enable_ifstd::is_same的重载似乎有效。不过不是很漂亮。请注意,这些都是c++11的特性。

struct A {};
struct B {};
struct C {
    template<class Cont>
    void operator()(const Cont& c, typename std::enable_if<std::is_same<typename Cont::value_type, A>::value>::type * = NULL) const {
        std::cout << "a";
    }
    template<class Cont>
    void operator()(const Cont& c, typename std::enable_if<std::is_same<typename Cont::value_type, B>::value>::type * = NULL) const {
        std::cout << "b";
    }
};
int main() {
    std::vector<A> a;
    std::list<B> b;
    C c;
    c(a);
    c(b);
}

是的,这应该是可能的。Arkanosis有一个很好的解决方案,但如果你想使用模板专业化:

class A {};
class B {};
template <template <typename , typename > class Z, class Elem> struct C
{    
    void operator()(const Z<Elem, std::allocator<Elem>>& v) {   std::cout << "General implement" << std::endl; }
};
template <template <typename, typename > class Z> struct C<Z,B>
{    
    void operator()(const Z<B, std::allocator<B>>& v) {   std::cout << "Specialized implement" << std::endl; }
};

然后一些客户端代码:

    #include <iostream>
    #include <vector>
    using namespace std;
    int main(int argc, char** argv) 
    {
    std::vector<A> as;
    std::list<B> bs;
    C<vector,A> ca;
    ca(as);
    C<list,B> cb;
    cb(bs);
    }

如果您想处理来自同一个C风格类的不同容器类型,您可以从C结构的模板派生,例如class MultiContainerHandlerForA : public C<vector,A>, public C<list,A>