C ++模板化成员函数作为另一个模板化类的接口

时间:2012-12-28 00:28:15

标签: c++ templates

我想创建一个类作为一组专用模板类的接口。例如:

template<typename T>
class ThingDoer {
    public:
        void Method()
        {
            // do something;
        }
};

class ThingDoerInterface {
    public:
        template<typename T>
        void Method()
        {
            // call ThingDoer<T>::Method(); somehow
        }
};

int main()
{
    ThingDoerInterface i;
    i.Method<int>();
    i.Method<char>();
    // etc.

    return 0;
}

我想要的对象的通用要求看起来像这样:

  • 用户只需要创建一个非模板化的对象实例。
  • 但是可以存在多个实例,并且预计它们是独立的。
  • 该对象将从类型A派生的(用户定义的)对象的实例与从类型B派生的(一个或多个)对象相关联。
  • 用户可以根据A的类型调用对B做某事的对象的方法。

我有一个基于std::unordered_multimap的实际问​​题的工作解决方案,但我很感兴趣,如果这样的事情可以单独用模板完成。

编辑:

这是一个更具体的例子,我希望能说明我实际上要做的事情。

class ABase {
    public:
        virtual ~ABase() {}
};

class A1 : public ABase {};
class A2 : public ABase {};

class BBase {
    public:
        virtual ~BBase() {}
};
class B1 : public BBase {};
class B2 : public BBase {};


class ThingDoerInterface {
    public:
        template<typename T>
        void Store(BBase* b_ptr)
        {
            // store the B pointer with the type of T as a key
            // (T will be A1 or A2)
        }

        template<typename T>
        void Recall()
        {
            // call all the stored B pointers associated with the type of T
        }
};

int main()
{
    ThingDoerInterface i;

    B1* b_one_ptr = new B1;
    B2* b_two_ptr = new B2;

    i.Store<A1>(b_one_ptr);
    i.Store<A1>(b_two_ptr);

    i.Store<A2>(b_one_ptr);

    i.Recall<A1>(); // do something with b_one_ptr and b_two_ptr
    i.Recall<A2>(); // do something with b_one_ptr

    delete b_two_ptr;
    delete b_one_ptr;

    return 0;
}

我用std::unordered_multimap做了这个,但我想知道的是,是否可以像这样存储关联:

template<typename T>
class ThingDoer {
    public:
        void Store(BBase* b_ptr)
        {
            b_ptrs.push_back(b_ptr);
        }

        void Recall()
        {
            // do something with the b_ptrs associated with the type of T
        }
    private:
        std::vector<BBase*> b_ptrs;
};

但不知何故在ThingDoerInterface中这样做。

1 个答案:

答案 0 :(得分:3)

我不一定说它值得复杂,但是......

#include<iostream>
#include<vector>
using namespace std;

class repo {
public:
  repo(){
    id = highestid++;
  }
  template<typename T>
  T& get() {
    vector<T>& vec = data<T>::vec;
    if (vec.size() <= id) {
      vec.resize(id+1);
    }
    return vec[id];
  }
private:
  template<typename T>
  struct data {
    static vector<T> vec;
  };
  int id;
  static int highestid;
};
/*static*/ int repo::highestid = 0;
template<typename T>
/*static*/ vector<T> repo::data<T>::vec;

main(){
  repo a, b;
  a.get<int>() = 42;
  b.get<int>() = 54;
  a.get<float>() = 4.2;
  b.get<float>() = 5.4;
  cout << a.get<int>() << ", " << b.get<int>() << ", " << a.get<float>() << ", " << b.get<float>() << endl;
}

我写它是为了快速查找。第一次为给定的仓库调用get时,会使其他仓库返回的所有引用无效,并且销毁仓库不会清理任何内容。但是如果你有少量的回购,其生命周期基本上是整个程序,那应该没问题。