开发者

"Using" directive fails within template

I understand that the member names o开发者_如何学编程f a base-class template are hidden within the scope of a derived class, and therefore must be accessed using this->foo or Base<T>::foo. However, I recall that C++ also allows you to use the using keyword, which can come in handy in a derived-class function which frequently accesses a base-class variable. So, in order to avoid cluttering up the function with this-> everywhere, I'd like to use the using keyword.

I know I've done this before, but for whatever reason I can't get it to work now. I'm probably just doing something stupid, but the following code won't compile:

template <class T>
struct Base
{
   int x;
};

template <class T>
struct Derived : public Base<T>
{
   void dosomething()
   {
     using Base<T>::x; // gives compiler error
     x = 0;
   }
};

int main()
{
   Derived<int> d;
}

The error, (with GCC 4.3) is: error: ‘Base<T>’ is not a namespace

Why doesn't this work?


It doesn't work because C++ language has no such feature and never had. A using-declaration for a class member must be a member declaration. This means that you can only use in class scope, but never in local scope. This all has absolutely nothing to do with templates.

In other words, you can place your using-declaration into class scope

struct Derived : public Base<T> {
  ...
  using Base<T>::x;
  ...
};

but you can't have it inside a function.

Using-declarations for namespace members can be placed in local scope, but using-declarations for class members cannot be. This is why the error message complains about Base<T> not being a namespace.


Outside class scope (if you are in a block etc), you can only name namespace members in a using declaration.

If you don't want to place that using declaration into the scope of Derived (which IMO is the favorable solution), your other option is to use a reference

int &x = this->x;
x = 0;

It should be noted that this is semantically different, because it

  • Forces a definition to exist for Base<T>::x, which might not be the case for static const data members
  • Forces Base<T>::x to be of type int& or be convertible to type int&.

Otherwise, if you want to avoid using this-> all again, I don't see other options.


template <class T>
struct Base
{
   int x;
};

template <class T>
struct Derived : public Base<T>
{
   using Base<T>::x;
   void dosomething()
   {
     x = 0;
   }
};

int main()
{
   Derived<int> d;
}

As others said, it is working only class scope.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜