Why, when a template class inherits from another template class, do typedefs need to be edited and functions assigned to calls?

When a template class is inherited from another template class, typedefs in the base class must be overridden (that is, they are not automatically inherited), and function calls in the base class must be qualified. Why is this? Isn't that already clear?

So, if I have 20 template classes, all defining the same typedefs, I cannot imagine the base class containing these definitions and inherit from it, since I have to redefine typedefs in any case in each class, which defeats the goal . This makes the source code unnecessarily verbose.

I see that this was discussed in this question , but I do not understand the comment

C ++ name lookup rules determine that a name is used only in template base classes if it depends on the template parameter (if it is a "dependent name"). If the name does not depend on the template parameter, it is not executed there.

What is the reason for this? It makes no sense to me.

Perhaps the following code snippet illustrates my question better:

#include <iostream> template <unsigned N, typename T> struct A { typedef TU; static void foo(T x) { std::cout << N + x << "\n"; } }; template <unsigned N, typename T> struct B : public A<N, T> { // Why do I have to redeclare U? Isn't is unambiguous already? typedef typename A<N, T>::UU; // why do I have to specify B::? Isn't it unambiguous already? static void zoo(U x) { B::foo(x); } }; int main() { B<2,int>().zoo(3); B<2,double>().zoo(3.5); return 0; } 
+7
c ++ typedef templates
source share
2 answers

The main reason is that classes can be specialized:

 template<class T> struct A {}; template<class T> struct B : A<T> { typedef typename A<T>::referent target; void niceName() {A<T>::uglyName();} }; template<class T> struct A<T*> { typedef T referent; void uglyName(); }; B<int*>::target i; // OK: int 

Of course, the opposite case (where the primary template defines useful things, and we are just afraid that specialization may change or delete them) is more common, which makes the rule seem arbitrary.

+1
source share

This is due to a two-phase search. Quote from here :

  • Template definition time: during the initial analysis of a template, long before its creation, the compiler analyzes the template and looks for any "independent" names. The name is "independent" if the search results by name are independent of the template parameters and therefore will be the same from one instance of the template to another.
  • Template creation time: when creating a template instance, the compiler looks at any "dependent" names, now that it has the full set of template arguments to perform the search. The results of this search can (and often do!) Vary from one instance of the template to another.

So, during the initial parsing, the compiler considers that U is name-independent and tries to find it, and it cannot find anything because it is not allowed to search for the dependent base class. But if U was a dependent name, then the compiler will look for it during the instantiation phase and find it in the base class.

BTW: VS will easily compile this, but recently they have added a two-phase search capability.

+3
source share

All Articles