1

我读了这篇关于如何使用 C++ 中的 typename 关键字的精彩摘要:http: //pages.cs.wisc.edu/~driscoll/typename.html

我仍然想知道一个特定的例子:

template<typename T> class Outer{
  public:
    class Inner1{
       T t; 
    };
    class Inner2{
      int t; 
    };
};

template<typename T> void foobar(void)
{
  std::list<Outer<T>::Inner1> l;
}

从上面链接的文字中,我了解到我需要

std::list<typename Outer<T>::Inner1> l;

因为 Inner1 既是合格的又是从属的。

但是:Inner2 还需要一个让我感到困惑的类型名:首先,似乎很清楚 Inner2 是一种类型(嗯,这对于 Inner1 来说已经很清楚了)。其次,Inner2 完全不依赖于 T。对于所有可能的 T,Inner2 将是相同的(类型)!

使用模板内部的限定类型后是否需要 typedef?是否取决于模板参数?

4

2 回答 2

3

你的第二个假设是错误的。Inner2确实依赖于 T,因为每个 Outer 都有另一个 Inner2。如果您专门研究 Outer,那就清楚了:

template<> class Outer<char>{
public:
  class Inner1{
     T t; 
  };
  typedef int Inner2; 
};

而且即使你不专业,Outer<float>::Inner2可能Outer<long>::Inner2有相同的布局、成员、名称等,但它们不是同一类型!考虑访问 -Outer<long>::Inner2可以访问Outer<long>的私人成员,Outer<float>::Inner2但没有。

在以下特化中,Inner2 甚至不是类型:

template<> class Outer<long double>{
public:
  char Inner2(int); 
};
于 2012-12-05T09:41:27.467 回答
1

Outer<T>::Inner2确实取决于类型T,因为编译器不知道是什么类型的东西Inner2——无论是类型还是静态数据成员。所以是的,你需要在这里告诉编译器它是什么类型的东西typename,因为默认是假设它是一个非类型成员(例如一个静态数据成员、一个方法名、一个enum值)。

(这对于 C++03 来说是正确的——我假设这方面的规则在 C++11 中没有改变。)

于 2012-12-05T09:37:31.070 回答