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

时间:2014-04-18 10:25:15

标签: c++ templates containers template-specialization

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

4 个答案:

答案 0 :(得分:3)

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 << "A\n";
    }

    template <class T>
    void operator()(const T& container, Tag<B>) const
    {
        std::cout << "B\n";
    }
};

int main()
{
    std::vector<A> a;
    std::list<B> b;
    C c;
    c(a);
    c(b);
}

答案 1 :(得分:2)

您可以使用模板模板参数执行此操作。

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

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);
}

答案 2 :(得分:1)

是的,应该是可能的。 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>

答案 3 :(得分:1)

使用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);
}