web-dev-qa-db-ja.com

テンプレートと継承に関する「このスコープで宣言されていません」エラー

これが私の問題を再現するコードサンプルです:

_template <typename myType>
class Base {
public:
    Base() {}
    virtual ~Base() {}
protected:
    int myOption;
    virtual void set() = 0;
};

template <typename InterfaceType>
class ChildClass : public Base < std::vector<InterfaceType> >
{
public:
    ChildClass() {}
    virtual ~ChildClass() {}
 protected:
    virtual void set();
};

template <typename InterfaceType>
void ChildClass<InterfaceType>::set()
{
     myOption = 10;
}
_

main()での使用法:

_ChildClass<int> myObject;
_

次のエラーが表示されます(ubuntuではgcc 4.4.3)。

「myOption」はこのスコープで宣言されていません

私のChildClassに新しいテンプレートパラメータがない場合、これは正常に機能します。

_class ChildClass : public Base < std::vector<SomeConcreteType> >
_

編集する

私のsetメソッドが次のようになっている場合は、なんとか解決しました:

_Base<std::vector<InterfaceType> >::myOption = 10;
_

正常に動作します。それでも、なぜすべてのテンプレートパラメータを指定する必要があるのか​​はわかりません。

29
Tadzys

myOptionは依存名ではありません。つまり、テンプレートの引数に明示的に依存しないため、コンパイラは早期に検索しようとします。依存名にする必要があります。

template <typename InterfaceType>
void ChildClass<InterfaceType>::set()
{
     this->myOption = 10;
}

現在は、thisのタイプ、つまりテンプレート引数に依存しています。したがって、コンパイラーはインスタンス化時にそれをバインドします。

これは Two-phase name lookup と呼ばれます。

43
ybungalobill

C++ 03 14.6.2依存名

クラステンプレートまたはクラステンプレートのメンバーの定義で、クラステンプレートの基本クラスがテンプレートパラメーターに依存している場合、基本クラスのスコープは検査されませんクラステンプレートまたはメンバーの定義の時点での非修飾名ルックアップ中、またはクラステンプレートまたはメンバーのインスタンス化中。

次のコードが機能するはずです。

template <typename InterfaceType>
void ChildClass<InterfaceType>::set()
{
   Base<std::vector<InterfaceType> >::myOption = 10;
}
13
Eric Z