何时是“类型名称”关键字有必要吗? [英] When is the "typename" keyword necessary?

查看:93
本文介绍了何时是“类型名称”关键字有必要吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能重复:

正式地,什么是类型名称?

Possible Duplicate:
Officially, what is typename for?
Where and why do I have to put the template and typename keywords?

请考虑以下代码:

template<class K>
class C {
    struct P {};
    vector<P> vec;
    void f();
};

template<class K> void C<K>::f() {
    typename vector<P>::iterator p = vec.begin();
}

为什么在这个例子中需要typename关键字?
是否还有其他需要指定typename的情况?

Why is the "typename" keyword necessary in this example? Are there any other cases where "typename" must be specified?

推荐答案

长回答:C ++中有三层实体,它们是一个依赖名称,即嵌套在一个未知参数的模板实例中。 :值,类型和模板。所有这些都可以有名称,并且单独的名称不告诉你它是哪一层实体。

Long answer: There are three tiers of entities in C++: values, types, and templates. All of those can have names, and the name alone doesn't tell you which tier of entity it is. Rather, the information about the nature of a name's entity must be inferred from the context.

每当这个推断是不可能的,你必须指定它:

Whenever this inference is impossible, you have to specify it:

template <typename> struct Magic; // defined somewhere else

template <typename T> struct A
{
  static const int value = Magic<T>::gnarl; // assumed "value"

  typedef typename Magic<T>::brugh my_type; // decreed "type"
  //      ^^^^^^^^

  void foo() {
    Magic<T>::template kwpq<T>(1, 'a', .5); // decreed "template"
    //        ^^^^^^^^
  }
};

这里的名称 Magic< T> :: gnarl Magic< T> :: brugh Magic< T> :: kwpq 必须加以说明,因为这是不可能的:因为 Magic 是一个模板, 类型 Magic< T& code>取决于 T - 可能存在与主模板完全不同的专业化。

Here the names Magic<T>::gnarl, Magic<T>::brugh and Magic<T>::kwpq had to be expliciated, because it is impossible to tell: Since Magic is a template, the very nature of the type Magic<T> depends on T -- there may be specializations which are entirely different from the primary template, for example.

使得 Magic< T> :: gnarl 一个依赖名称的原因是我们在一个模板定义中,其中 T 未知。如果我们使用 Magic< int> ,这将是不同的,因为编译器知道(你承诺!) Magic< int& / code>。

What makes Magic<T>::gnarl a dependent name is the fact that we're inside a template definition, where T is unknown. Had we used Magic<int>, this would be different, since the compiler knows (you promise!) the full definition of Magic<int>.

(如果你想自己测试,下面是 Magic 你可以使用。为简洁起见,在专门化中使用 constexpr ;如果你有一个旧的编译器,请随意更改静态成员常量声明为旧式前C ++ 11形式。)

(If you want to test this yourself, here's a sample definition of Magic that you can use. Pardon the use of constexpr in the specializaation for brevity; if you have an old compiler, feel free to change the static member constant declaration to the old-style pre-C++11 form.)

template <typename T> struct Magic
{
  static const T                    gnarl;
  typedef T &                       brugh;
  template <typename S> static void kwpq(int, char, double) { T x; }
};
template <> struct Magic<signed char>
{
  // note that `gnarl` is absent
  static constexpr long double brugh = 0.25;  // `brugh` is now a value
  template <typename S> static int kwpq(int a, int b) { return a + b; }
};

用法:

int main()
{
  A<int> a;
  a.foo();

  return Magic<signed char>::kwpq<float>(2, 3);  // no disambiguation here!
}

这篇关于何时是“类型名称”关键字有必要吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆