Typedefのみを含む基本クラスを定義しようとしています。
template<typename T>
class A
{
public:
typedef std::vector<T> Vec_t;
};
template<typename T>
class B : public A<T>
{
private:
Vec_t v; // fails - Vec_t is not recognized
};
BでVec_tが認識されないというエラーを受け取り、明示的に記述する必要があるのはなぜですか?
typename A<T>::Vec_t v;
この質問は重複していると思いますが、今は見つけることができません。 C++標準では、14.6.2/3に従って名前を完全に修飾する必要があるとされています。
クラステンプレートまたはクラステンプレートのメンバーの定義で、クラステンプレートの基本クラスがテンプレートパラメーターに依存している場合、非修飾名のルックアップ中に基本クラススコープは検査されませんクラステンプレートまたはメンバーの定義時点、またはクラステンプレートまたはメンバーのインスタンス化中。
UPD:最終的に重複が見つかりました: ここにあります 。
テンプレートの場合、依存名およびnondependentという名前があります。
名前がテンプレートパラメータTに依存する場合、そのdependent名前と、パラメータTに依存しない他の名前はindependent名前。
ルールは次のとおりです。コンパイラは、非依存名(Vec_tなど)を検索するときに、依存ベースクラス(Aなど)を検索しません。その結果、コンパイラーは、それらが存在することはもちろんのこと、型であることも知りません。
コンパイラは、Vec_t
は、T
を認識するまでは型です。なぜなら、A<T>
どこ A<T>:: Vec_t
はデータメンバーです
したがって、解決策はtypenameを使用することです
typename A<T>::Vec_t v; ← good
このことをお勧めします https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-types 。
古い(壊れた)リンク: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18
コンパイラはVec_t
はタイプに名前を付けます。例えば、 A<T>
はT=int
〜not特定のtypedef
を持ちます。
完全を期すために、この迷惑を少し軽減する方法を次に示します。
using declaration
で派生クラススコープにこれらの名前をインポートするだけです。template<typename T>
class A
{
public:
typedef std::vector<T> Vec_t;
};
template<typename T>
class B : public A<T>
{
public:
using typename A<T>::Vec_t;
// .........
private:
Vec_t v;
};
派生クラスで継承されたtypedef
について複数の言及がある場合に役立ちます。また、毎回typename
を追加する必要はありません。
コンパイラはVec_t
がどこから来たのかわからないため、Vec_t
の使用を明示的に修飾する必要があります。
クラステンプレートAは特殊化されている可能性があるため、Aの構造については何も想定できません。特殊化には、typedefではないVec_t
が含まれるか、メンバーVec_t
がまったく含まれない場合があります。
Vec_tは依存名ではないため、コンパイラはテンプレート(この場合はベースクラス)をインスタンス化せずに、それが何であるかを知る必要があります。本当に違いはありません:
template <class T>
class X
{
std::string s;
}
ここでも、名前はテンプレート引数Tに依存しないため(コンパイラが想定できる限り)、Xがインスタンス化されていない場合でも、コンパイラはstd :: stringについて知る必要があります。
全体として、テンプレートベースクラスのtypedefは、派生クラスで使用するのはむしろ役に立たないようです。ただし、typedefはユーザーにとっては便利です。
この概念は、std::vector<T>
の使用方法に関連付けることができます。たとえば、std::vector<int> Foo
がある場合。ここで、そのメンバー型のいずれかを使用することにしました。iterator
と言いましょう。このシナリオでは、明示的に言及しています
std::vector<int>::iterator foo_iterator;
同様に、あなたの場合、Vec_t
のtemplate <typename T> class A
のパブリックメンバタイプを使用するには、次のように明示的に宣言する必要があります。
A<T>::Vec_t v;
OR
A<int>::Vec_t int_type;