3

一連の特殊なテンプレートクラスへのインターフェイスとして機能するクラスを作成したいと思います。例えば:

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

私が欲しいオブジェクトの一般的な要件は次のようになります。

  • ユーザーは、オブジェクトのテンプレート化されていないインスタンスを1つだけ作成する必要があります。
  • ただし、複数のインスタンスが存在する可能性があり、独立していることが期待されます。
  • オブジェクトは、タイプAから派生した(ユーザー定義の)オブジェクトのインスタンスを、タイプBから派生した(1つ以上の)オブジェクトに関連付けます。
  • ユーザーは、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しかし、どういうわけかそうします。

4

1 に答える 1

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を呼び出すと、他のリポジトリから返されたすべての参照が無効になり、リポジトリを破棄しても何もクリーンアップされません。ただし、ライフタイムが基本的にプログラム全体であるリポジトリが少数ある場合は、問題ありません。

于 2013-01-22T18:37:09.937 に答える