为什么当模板类继承自另一个模板类时,需要重新指定typedef并且函数调用是否合格?

时间:2018-01-11 04:32:11

标签: c++ templates typedef

当模板类继承自另一个模板类时,必须再次重新定义基类中的typedef(即它们不会自动继承),并且需要限定基类中的函数调用。这是为什么?这不是明确的吗?

因此,如果我有20个模板类,都定义了相同的typedef,我无法引入包含这些定义的基类并继承它,因为我必须在每个类中重新定义typedef,这会使目的。这使源代码变得不必要地冗长。

我可以看到这已在question中讨论,但我不理解评论

  

C ++名称查找规则指定仅在模板化基类中搜索名称(如果它取决于模板参数(如果它是“依赖名称”))。如果名称不依赖于模板参数,则不会在那里搜索。

这是什么原因?这对我没用。

或许,以下代码段会更好地说明我的问题:

#include <iostream>

template <unsigned N, typename T>
struct A
{
   typedef T U;
   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>::U U;

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

2 个答案:

答案 0 :(得分:3)

由于两阶段查找而发生了这种情况。引自here

  
      
  1. 模板定义时间:最初解析模板时,在实例化之前,编译器会解析模板并   查找任何&#34;非依赖&#34;名。名字是&#34;非依赖&#34;如果   名称查找的结果不依赖于任何模板参数,和   因此,从一个模板实例化到另一个模板实例化将是相同的。
  2.   
  3. 模板实例化时间:当模板实例化时,编译器会查找任何依赖的&#34;名字,现在它已经完整   用于执行查找的模板参数。这个查找的结果   可以(并经常做!)从一个模板实例化到另一个模板实例化。
  4.   

因此,在初始解析期间,编译器认为U是非依赖名称并尝试查找它并且它无法找到任何内容,因为它不允许查看依赖基类。但是如果U是依赖名称,那么编译器会在实例化阶段查找它并在基类中找到它。

BTW:VS很容易编译,但最近他们增加了两阶段查找的可能性。

答案 1 :(得分:1)

根本原因是课程可以专业化:

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

当然,相反的情况(主要模板定义有用的东西,我们只是担心专业化可能会改变或删除它们)更常见,这使得规则似乎是任意的。 / p>