0

サポートされているタイプを既存のレガシーstd::list操作関数に追加することについて具体的な質問があります。テンプレートを使ってこれを試みましたが成功しなかったので、テンプレートをより適切に使用する方法や、まったく異なるメカニズムを使用する方法についてアドバイスをいただければ幸いです。以下の私のシナリオを見て、これについて何か考えがあれば教えてください。助けてくれてありがとう!

私は現在、タイプAの2つのstd :: listを持っており、それらの挿入/削除/ゲッター/etc関数を持っています。このための簡略化されたコードスニペットを以下に示します。

typedef std::list<A*> TListA;
TListA ListA1;
TListA ListA2;

void InsertIntoListA(A* pA)
{
    TListA& ListA = IsBoo()? ListA1 : ListA2;
    ListA.push_back(pA);
}

ここで、タイプBを追加する必要があることがわかり、テンプレートを使用してこの新しいタイプを追加することを検討しました(以下を参照)が、これには2つの問題があることがわかりました。

template <typename T>
void InsertIntoListT(T* pT)
{
    std::list<T*>& List;

    if (IsA())
        List = IsBoo()? ListA1 : ListA2;
    else
        List = IsBoo()? ListB1 : ListB2;      

    List.push_back(pT);   
}

問題1:「std :: list&List」は参照によるものであるため、実際のリストに割り当てる必要があるため、使用できません。だから私はこのようなものになってしまいますが、これは理想的ではありません。

template <typename T>
void InsertIntoListT(T* pT)
{    
    if (IsA()) {
        TListA& ListA = IsBoo()? ListA1 : ListA2;
        ListA.push_back(pT);   
    } else {
        TListB& ListB = IsBoo()? ListB1 : ListB2;      
        ListB.push_back(pT);   
    }     
}

問題2:AからB、またはBからAのいずれかで型変換エラーが発生します。これは、テンプレートTが与えられると、コンパイラが「ListA.push_back」と「ListB.push_back」の4つの可能性すべてを列挙するためだと思います。これにより、AをリストAに挿入し、BをリストAに挿入し、AをリストBに挿入し、BをリストBに挿入しますが、これらのうち2つだけが有効です。だから私はこのようなものになってしまい、テンプレートを使用する目的を損なうと思います。

template <typename T>
void InsertIntoListT(T* pT)
{    
    if (IsA()) {
        TListA& ListA = IsBoo()? ListA1 : ListA2;
        ListA.push_back(reinterpret_cast<A*>(pT));
    } else {
        TListB& ListB = IsBoo()? ListB1 : ListB2;      
        ListB.push_back(reinterpret_cast<B*>(pT));
    }     
}
4

2 に答える 2

1

すべてを1つの機能に混ぜないでください。それは非常に悪い習慣です。次のようなものを使用します

void InsertIntoListImpl(A* p)
{
   (IsBoo() ? ListA1 : ListA2).push_back(p);
}

void InsertIntoListImpl(B* p)
{
   (IsBoo() ? ListB1 : ListB2).push_back(p);
}

template<typename T>
void InsertIntoList(T* p)
{
   InsertIntoListImpl(p);
}

またはいくつかの特性、または何か他のもの。しかしとにかく、1つの関数に多くの条件はありません。

実際のリストを挿入用の関数に渡してみませんか?いずれ良くなるだろう。

于 2013-01-28T07:39:30.173 に答える
1

明らかに、各テンプレートのインスタンス化は2つのタイプのうちの1つしか認識しないため、関数テンプレート内でリストタイプの切り替えを行うことはできません。したがって、関数の外部で切り替えを行う必要があります。可能性は次のとおりです。

TListA& getList(bool isBoo, A* /*dummy*/)
{
  return isBoo ? ListA1 : ListA2;
}

TListB& getList(bool isBoo, B* /*dummy*/)
{
  return isBoo ? ListB1 : ListB2;
}

template <typename T>
void InsertIntoListT(T* pT)
{    
  auto& theList = getList(IsBoo(), (T*)NULL);
  theList.push_back(pT);
}

ダミーはタイプsiwtching専用です-関数テンプレートと特殊化を介して実行できますが、それは醜いです。リスト変数の実際の性質に応じて、getList機能は他の方法で記述できます。多分もっと一般的かもしれませんが、そうではないかもしれません。

于 2013-01-28T07:45:06.820 に答える