13

I'm aware of the fact that the 'dependent names' are not visible to the compiler by default. But I was told in answers to other SO questions (here, here, and ultimately on the C++ faq) that a using declaration may help.

So I tried.

A template base class:

// regardless of the fact that members are exposed...
template<typename T>
struct TBase {
   typedef T MemberType;
   MemberType baseMember;
   MemberType baseFunction() { return MemberType(); }
};

And a derived class, using the base's members:

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’
   }
};

I tried this out on ideone. It has gcc-4.3.3 and gcc-4.5.1

Is this expected behavior? How are we supposed to work around the 'dependent name' law for accessing parent template class' member typedefs?

Community
  • 1
  • 1
xtofl
  • 38,207
  • 10
  • 95
  • 177
  • This happens because of the two-phase name lookup (which not all compilers use by default). There are 4 solutions to this problem: **1)** Use the prefix `TBase::baseMember`, **2)** Use the prefix `this->baseMember`, **3)** Add a statement `using TBase::baseMember`, **4)** Use a global compiler switch that enables the permissive mode. The pros & cons and details of these solutions are described in https://stackoverflow.com/questions/50321788/a-better-way-to-avoid-public-member-invisibility-and-source-code-bloat-repetitio – George Robinson May 14 '18 at 14:10

1 Answers1

20

You probably want to do:

using MemberType = typename TBase<T>::MemberType; // new type alias syntax

or

typedef typename TBase<T>::MemberType MemberType; // old type alias syntax

The syntax using Base::member; can only be used to bring the declarations of non-type members into scope.


Also note that none of these are actually required, you can qualify each use (for types with the base, for non-types with either this-> or the base) and that will make the symbol dependent.

David Rodríguez - dribeas
  • 192,922
  • 20
  • 275
  • 473
  • Was stuck with this issue. Came across your answer and using "this->" in the derived class worked like a charm. Thanks. – Vaibhav Desai Dec 06 '12 at 22:31
  • actually, you may use using syntax but need typename `using typename TBase::MemberType;` seem to work for me – RiaD May 14 '16 at 22:43