4

内部でいくつかの STL リストを使用する小さなクラスがあります。

template<class T>
class MC_base {

  using OBJ_LIST  = std::list<T>;
  using OBJ_VAL   = typename OBJ_LIST::value_type;
  using OBJ_ITR   = typename OBJ_LIST::iterator;
  using OBJ_CITR  = typename OBJ_LIST::const_iterator;

  OBJ_LIST A,B,C;
  ...
};

ステートメントを使用してusing、クラス定義内に反復子を記述すると、きれいに見えます。

OBJ_ITR begin() { return A.begin(); };
OBJ_ITR end()   { return A.end();   };
OBJ_CITR begin() const { return A.begin(); };
OBJ_CITR end()   const { return A.end();   };

必要に応じて名前を単純に使用できるため、クラス定義内に新しい関数を記述するのは簡単OBJ_XXXXです。さらに、後でコンテナーの種類 (つまりstd::vector) を変更することにした場合、変更する必要があるのは 1 行だけで、新しいコンテナーがすべて同じアクションをサポートしている限り、すべてがシームレスになります。

これは問題ですが、クラス定義の外で新しいクラス関数を定義したい場合

template<class T>
OBJ_ITR MC_base<T>::foo(OBJ_ITR x) { ... }

using ステートメントを「引き出す」方法がわからないので、テンプレートで正しく機能し、過度に冗長になるすべての関数に対してそれらを定義しません。また、using ステートメントで名前空間を汚染したくありません。

usingテンプレートを使用する適切な方法はありますか?

4

2 に答える 2

5

クラスの外では、名前を修飾する必要があります。さらに、キーワードを使用して、これらの名前がす​​べての特殊化の型であることをコンパイラーに約束する必要がありますtypename

template<class T>
typename MC_base<T>::OBJ_ITR MC_base<T>::foo( typename MC_base<T>::OBJ_ITR x ) { ... }

9.3p2 では、

クラス定義の外に現れるメンバー関数定義は、クラス定義を囲む名前空間スコープに現れるものとします。

これにより、これらの名前が存在する定義に、よりネストされたスコープを使用できなくなります。これらの名前がテンプレート パラメータに依存するという問題は言うまでもありません。


最善の解決策は、おそらくこれらの関数をインラインで記述することです。これらはテンプレート クラスのメンバーであるため、ヘッダー ファイルに含める必要があります。

于 2013-09-03T14:43:00.510 に答える