「typedef」を「template」のベースクラスから派生クラスに伝播する
-
10-07-2019 - |
質問
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 ++ Standardは、14.6.2 / 3に従って名前を完全に修飾する必要があると述べています。
クラステンプレートまたはクラステンプレートのメンバーの定義で、クラステンプレートの基本クラスがテンプレートパラメータに依存している場合、非修飾名のルックアップ中に基本クラススコープは検査されません >クラステンプレートまたはメンバーの定義の時点で、またはクラステンプレートまたはメンバーのインスタンス化中に。
他のヒント
テンプレートの場合、依存名および非依存名と呼ばれるものがあります。
名前がテンプレートパラメータTに依存する場合、その dependent 名と、パラメータTに依存しない他の名前は独立名です。
ここにルールがあります:コンパイラは 依存する基底クラスを調べます(たとえば A)非依存を検索する場合 名前(Vec_tなど)。結果として、 コンパイラーはそれらを知らない タイプはもちろん存在します。
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&lt; T&gt;
は、 T = int
に特化して、特定の typedef
を持たない 場合があります。
完全を期すため、この迷惑を少し軽減する方法を以下に示します。
- 派生クラスでこれらの型を再定義するか、より良い-と同様に メソッド-
- 派生クラスのスコープにある
using宣言
でこれらの名前をインポートするだけです:
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&lt; T&gt;
の使用方法に関連付けることができます。たとえば、 std :: vector&lt; int&gt;がある場合Foo
。ここで、 iterator
のように、そのメンバー型のいずれかを使用することにしました。このシナリオでは、明示的に言及しています
std::vector<int>::iterator foo_iterator;
同様に、 template&lt; typename T&gt;の
、明示的に宣言する必要があります Vec_t
のパブリックメンバータイプを使用するには、クラスA
A<T>::Vec_t v;
OR
A<int>::Vec_t int_type;