6

私は解決しようとしているこのパズルを持っています。基本的には、次の例に要約されます。

template <typename CT>
struct A
{
  typedef typename CT::VALUE_T FOO; // FOO is dependent on CT
};

template <typename CT>
struct B
{
  typedef typename CT::BAR BAR;

  BAR foo() {}
};

template <typename DT>
struct C : B<C<DT> >
{
  typedef DT VALUE_T;

  typedef typename A<C>::FOO BAR;
};

int main () {
  C<int> c;
}

上記の説明を試みることはできますが (約 3 回試行してテキストを削除しました!)、基本的に要件は次のとおりです。

  1. CBtyped with C(CRTP の利用)から継承する必要があります。つまり、B<C<>>
  2. Cインスタンス化できる唯一のものですA(つまりA、で入力する必要がありますC
  3. Aは定義できる唯一のものですFOO(FOOはタイプに依存しCT、関係は提示されたものよりも複雑です)

問題 (上記のコードでわかるように) は、BAR型が 内でのみ使用可能であり、インスタンス化さCれたときにこれが不完全であるため、テンプレート引数( )の型が表示されないことです。残念ながら 内では、型は関数への引数として使用され、型を返します (つまり、関数スコープに限定されないため、typedef を関数スコープに単純に移動することはできません)。BBBARCTC<int>BBAR

これを回避する方法はありますか?上記の関係を壊すことはできません (最後の手段でない限り)。おそらくc ++ 11を使用すると、 typedefを使用autoする必要性を回避できますが、これは現在のところまだオプションではありません。BARB

編集: @bitmasks のコメントに続き、さらに情報が追加されました。

  1. とのコードはABさまざまな状況でかなりの数のバイナリで使用されています。この場合の唯一のユニークな状況は、Cから派生したものBであり、他のインスタンスでは、 から派生したもののインスタンスをC所有していますB
  2. テンプレート引数は、 および の既存の使用を変更する必要のない値にデフォルト設定できる限り、(およびで)A変更できます。同じタイプのセットが、デフォルトのテンプレート パラメーターとして、またはその他のメカニズムとして使用できる必要があります。BAB

ここでテンプレートを使用しているのは、密結合が必要であり、さまざまな状況でコードを使用できる柔軟性が必要だったからです。

コンポーネントの説明:

  • Aコンテナーとして説明するのが最も適切であり、FOO実際には反復子です。含まれるものは、テンプレート パラメーターの typedef によって定義されます。
  • Bのインスタンスが所有するいくつかのコンポーネントによって呼び出される一連の関数を含む基本クラスとして説明するのが最も適切ですC。前のケースでは、これらのコンポーネントには から派生したものへの参照が渡されましたB(そして、それらのものは によって所有されCています)。この例では、Cそれ自体への参照を提供しています。

主な複雑さは、コンテナへのアクセスから発生します。以前はとAの間の関係は のインスタンスを持っていましたが、現在は のインスタンスです- このセマンティクスの変更により、型がクラスに注入される方法が壊れます。BCC BC B

4

1 に答える 1

4

typedefデフォルトのテンプレートパラメータを使用して、周期的な要件に対処できると思います。以下は(私があなたの質問を理解している限り)意図したとおりに機能し、(ほぼ)元のコードのすべての自由を残します:

template <typename CT, typename CTVALUE_T = typename CT::VALUE_T>
struct A
{
    //typedef typename CT::VALUE_T FOO; // FOO is dependent on CT
    typedef CTVALUE_T FOO; // FOO is dependent on CT
};

template <typename CT, typename CTBAR = typename CT::BAR>
struct B
{
    //typedef typename CT::BAR BAR;
    typedef CTBAR BAR;

    BAR foo() {return 0;}
};

template <typename DT> struct VALUE_T__from__DT {
  typedef DT VALUE_T;
};

template <typename DT, template <class T> class _C_ > struct BAR__from__DT {
  typedef typename A<_C_<DT> , typename VALUE_T__from__DT<DT>::VALUE_T >::FOO BAR;
};

template <typename DT>
struct C : B<C<DT>, typename BAR__from__DT<DT, C >::BAR >
{
    //typedef DT VALUE_T;

    //typedef typename A<C>::FOO BAR;
};

int main () {
    C<int> c;
    int x = c.foo();
    (void)x;
    return 0;
}

ヘルパーテンプレートタイプの名前はひどいです、おそらくあなたはより良い名前を見つけることができます。

核となるトリックは、問題のあるtypedefsの定義を別のメタコンテナー(つまり、特性のコンテナー)に入れて、そこでブードゥーを実行できるようにすることです。

私は不要なtypedefをコメントアウトしました(ただし、私がそこで何をしているのかを理解するためのより良い機会があるように、それらをそこに残しました)。

それはあなたのニーズに合っていますか?

于 2011-12-06T17:00:42.837 に答える