模板基类typedef成员不可见

14
我知道“依赖名称”默认情况下对编译器不可见。但是在回答其他SO问题(这里这里和最终在C++ FAQ上)时,有人告诉我可以使用using声明来解决。所以我尝试了一下。
一个模板基类:
// regardless of the fact that members are exposed...
template<typename T>
struct TBase {
   typedef T MemberType;
   MemberType baseMember;
   MemberType baseFunction() { return MemberType(); }
};

一个派生类,使用基类成员:

template<typename T>
struct TDerived : public TBase<T> {
   // http://www.parashift.com/c++-faq-lite/nondependent-name-lookup-members.html
   // tells us to use a `using` declaration.
   using typename TBase<T>::MemberType;
   using TBase<T>::baseFunction;
   using TBase<T>::baseMember;

   void useBaseFunction() { 
      // this goes allright.
      baseFunction();
      ++baseMember;

      // but here, the compiler doesn't want to help...
      MemberType t; //error: expected `;' before ‘t’
   }
};

我在ideone上尝试了这个。它有gcc-4.3.3和gcc-4.5.1。
这是期望的行为吗?我们应该如何解决访问父模板类成员typedef的“依赖名称”法律问题?

这是由于双阶段名称查找引起的(并非所有编译器都默认使用)。解决此问题有4种方法:1) 使用前缀 TBase<T>::baseMember2) 使用前缀 this->baseMember3) 添加语句 using TBase<T>::baseMember4) 使用启用宽松模式的全局编译器开关。这些解决方案的优缺点和详细信息在 https://dev59.com/Eek5XIcBkEYKwwoY7eQE 中有描述。 - George Robinson
1个回答

20

你可能想做的是:

using MemberType = typename TBase<T>::MemberType; // new type alias syntax
或者
typedef typename TBase<T>::MemberType MemberType; // old type alias syntax

语法 using Base::member; 只能用于将非类型成员的声明引入作用域。


还要注意的是,这些都不是必需的,您可以对每个使用进行限定(对于具有基类的类型,使用 base;对于非类型,使用 this-> 或基类)这将使符号变为相关。


卡在这个问题上了。看到你的答案,使用派生类中的“this->”就像魔法一样解决了问题。谢谢。 - Vaibhav Desai
2
实际上,您可以使用语法,但需要typename using typename TBase<T>::MemberType; 对我来说似乎可行。 - RiaD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接