WEB开发网
开发学院软件开发C++ C++箴言:理解typename两个含义 阅读

C++箴言:理解typename两个含义

 2008-03-08 21:27:41 来源:WEB开发网   
核心提示:在下面的 template declarations(模板声明)中 class 和 typename 有什么不同? template class Widget; // uses "class" template class Widget; // uses "typename"

  在下面的 template declarations(模板声明)中 class 和 typename 有什么不同?

  template class Widget; // uses "class"
  template class Widget; // uses "typename"

  答案:没什么不同。在声明一个 template type parameter(模板类型参数)的时候,class 和 typename 意味着完全相同的东西。一些程序员更喜欢在所有的时间都用 class,因为它更轻易输入。其他人(包括我本人)更喜欢 typename,因为它暗示着这个参数不必要是一个 class type(类类型)。少数开发者在任何类型都被答应的时候使用 typename,而把 class 保留给仅接受 user-defined types(用户定义类型)的场合。但是从 C++ 的观点看,class 和 typename 在声明一个 template parameter(模板参数)时意味着完全相同的东西。

  然而,C++ 并不总是把 class 和 typename 视为等同的东西。有时你必须使用 typename。为了理解这一点,我们不得不讨论你会在一个 template(模板)中涉及到的两种名字。

  假设我们有一个函数的模板,它能取得一个 STL-compatible container(STL 兼容容器)中持有的能赋值给 ints 的对象。进一步假设这个函数只是简单地打印它的第二个元素的值。它是一个用糊涂的方法实现的糊涂的函数,而且就像我下面写的,它甚至不能编译,但是请将这些事先放在一边——有一种方法能发现我的愚蠢:

  template // PRint 2nd element in
  void print2nd(const C& container) // container;
  {
  // this is not valid C++!
  if (container.size() >= 2) {
  C::const_iterator iter(container.begin()); // get iterator to 1st element
  ++iter; // move iter to 2nd element
  int value = *iter; // copy that element to an int
  std::cout << value; // print the int
  }
  }

  我突出了这个函数中的两个 local variables(局部变量),iter 和 value。iter 的类型是 C::const_iterator,一个依靠于 template parameter(模板参数)C 的类型。一个 template(模板)中的依靠于一个 template parameter(模板参数)的名字被称为 dependent names(依靠名字)。当一个 dependent names(依靠名字)嵌套在一个 class(类)的内部时,我称它为 nested dependent name(嵌套依靠名字)。C::const_iterator 是一个 nested dependent name(嵌套依靠名字)。实际上,它是一个 nested dependent type name(嵌套依靠类型名),也就是说,一个涉及到一个 type(类型)的 nested dependent name(嵌套依靠名字)。

  print2nd 中的另一个 local variable(局部变量)value 具有 int 类型。int 是一个不依靠于任何 template parameter(模板参数)的名字。这样的名字以 non-dependent names(非依靠名字)闻名。(我想不通为什么他们不称它为 independent names(无依靠名字)。假如,像我一样,你发现术语 "non-dependent" 是一个令人厌恶的东西,你就和我产生了共鸣,但是 "non-dependent" 就是这类名字的术语,所以,像我一样,转转眼睛放弃你的自我主张。)

  nested dependent name(嵌套依靠名字)会导致解析困难。例如,假设我们更加愚蠢地以这种方法开始 print2nd:

  template
  void print2nd(const C& container)
  {
  C::const_iterator * x;
  ...
  }

  这看上去似乎是我们将 x 声明为一个指向 C::const_iterator 的 local variable(局部变量)。但是它看上去如此仅仅是因为我们知道 C::const_iterator 是一个 type(类型)。但是假如 C::const_iterator 不是一个 type(类型)呢?假如 C 有一个 static data member(静态数据成员)碰巧就叫做 const_iterator 呢?再假如 x 碰巧是一个 global variable(全局变量)的名字呢?在这种情况下,上面的代码就不是声明一个 local variable(局部变量),而是成为 C::const_iterator 乘以 x!当然,这听起来有些愚蠢,但它是可能的,而编写 C++ 解析器的人必须考虑所有可能的输入,甚至是愚蠢的。

  在下面的 template declarations(模板声明)中 class 和 typename 有什么不同?

  template class Widget; // uses "class"
  template class Widget; // uses "typename"

  答案:没什么不同。在声明一个 template type parameter(模板类型参数)的时候,class 和 typename 意味着完全相同的东西。一些程序员更喜欢在所有的时间都用 class,因为它更轻易输入。其他人(包括我本人)更喜欢 typename,因为它暗示着这个参数不必要是一个 class type(类类型)。少数开发者在任何类型都被答应的时候使用 typename,而把 class 保留给仅接受 user-defined types(用户定义类型)的场合。但是从 C++ 的观点看,class 和 typename 在声明一个 template parameter(模板参数)时意味着完全相同的东西。

  然而,C++ 并不总是把 class 和 typename 视为等同的东西。有时你必须使用 typename。为了理解这一点,我们不得不讨论你会在一个 template(模板)中涉及到的两种名字。
  假设我们有一个函数的模板,它能取得一个 STL-compatible container(STL 兼容容器)中持有的能赋值给 ints 的对象。进一步假设这个函数只是简单地打印它的第二个元素的值。
它是一个用糊涂的方法实现的糊涂的函数,而且就像我下面写的,它甚至不能编译,但是请将这些事先放在一边——有一种方法能发现我的愚蠢:

  template // print 2nd element in
  void print2nd(const C& container) // container;
  {
  // this is not valid C++!
  if (container.size() >= 2) {
  C::const_iterator iter(container.begin()); // get iterator to 1st element
  ++iter; // move iter to 2nd element
  int value = *iter; // copy that element to an int
  std::cout << value; // print the int
  }
  }

  我突出了这个函数中的两个 local variables(局部变量),iter 和 value。iter 的类型是 C::const_iterator,一个依靠于 template parameter(模板参数)C 的类型。一个 template(模板)中的依靠于一个 template parameter(模板参数)的名字被称为 dependent names(依靠名字)。当一个 dependent names(依靠名字)嵌套在一个 class(类)的内部时,我称它为 nested dependent name(嵌套依靠名字)。C::const_iterator 是一个 nested dependent name(嵌套依靠名字)。实际上,它是一个 nested dependent type name(嵌套依靠类型名),也就是说,一个涉及到一个 type(类型)的 nested dependent name(嵌套依靠名字)。

  print2nd 中的另一个 local variable(局部变量)value 具有 int 类型。int 是一个不依靠于任何 template parameter(模板参数)的名字。这样的名字以 non-dependent names(非依靠名字)闻名。(我想不通为什么他们不称它为 independent names(无依靠名字)。假如,像我一样,你发现术语 "non-dependent" 是一个令人厌恶的东西,你就和我产生了共鸣,但是 "non-dependent" 就是这类名字的术语,所以,像我一样,转转眼睛放弃你的自我主张。)

  nested dependent name(嵌套依靠名字)会导致解析困难。例如,假设我们更加愚蠢地以这种方法开始 print2nd:

  template
  void print2nd(const C& container)
  {
  C::const_iterator * x;
  ...
  }

  这看上去似乎是我们将 x 声明为一个指向 C::const_iterator 的 local variable(局部变量)。但是它看上去如此仅仅是因为我们知道 C::const_iterator 是一个 type(类型)。但是假如 C::const_iterator 不是一个 type(类型)呢?假如 C 有一个 static data member(静态数据成员)碰巧就叫做 const_iterator 呢?再假如 x 碰巧是一个 global variable(全局变量)的名字呢?在这种情况下,上面的代码就不是声明一个 local variable(局部变量),而是成为 C::const_iterator 乘以 x!当然,这听起来有些愚蠢,但它是可能的,而编写 C++ 解析器的人必须考虑所有可能的输入,甚至是愚蠢的。

  在下面的 template declarations(模板声明)中 class 和 typename 有什么不同?

  template class Widget; // uses "class"
  template class Widget; // uses "typename"

  答案:没什么不同。在声明一个 template type parameter(模板类型参数)的时候,class 和 typename 意味着完全相同的东西。一些程序员更喜欢在所有的时间都用 class,因为它更轻易输入。其他人(包括我本人)更喜欢 typename,因为它暗示着这个参数不必要是一个 class type(类类型)。少数开发者在任何类型都被答应的时候使用 typename,而把 class 保留给仅接受 user-defined types(用户定义类型)的场合。但是从 C++ 的观点看,class 和 typename 在声明一个 template parameter(模板参数)时意味着完全相同的东西。

  然而,C++ 并不总是把 class 和 typename 视为等同的东西。有时你必须使用 typename。为了理解这一点,我们不得不讨论你会在一个 template(模板)中涉及到的两种名字。

  假设我们有一个函数的模板,它能取得一个 STL-compatible container(STL 兼容容器)中持有的能赋值给 ints 的对象。进一步假设这个函数只是简单地打印它的第二个元素的值。它是一个用糊涂的方法实现的糊涂的函数,而且就像我下面写的,它甚至不能编译,但是请将这些事先放在一边——有一种方法能发现我的愚蠢:

  template // print 2nd element in
  void print2nd(const C& container) // container;
  {
  // this is not valid C++!
  if (container.size() >= 2) {
  C::const_iterator iter(container.begin()); // get iterator to 1st element
  ++iter; // move iter to 2nd element
  int value = *iter; // copy that element to an int
  std::cout << value; // print the int
  }
  }

  我突出了这个函数中的两个 local variables(局部变量),iter 和 value。
iter 的类型是 C::const_iterator,一个依靠于 template parameter(模板参数)C 的类型。一个 template(模板)中的依靠于一个 template parameter(模板参数)的名字被称为 dependent names(依靠名字)。当一个 dependent names(依靠名字)嵌套在一个 class(类)的内部时,我称它为 nested dependent name(嵌套依靠名字)。C::const_iterator 是一个 nested dependent name(嵌套依靠名字)。实际上,它是一个 nested dependent type name(嵌套依靠类型名),也就是说,一个涉及到一个 type(类型)的 nested dependent name(嵌套依靠名字)。

  print2nd 中的另一个 local variable(局部变量)value 具有 int 类型。int 是一个不依靠于任何 template parameter(模板参数)的名字。这样的名字以 non-dependent names(非依靠名字)闻名。(我想不通为什么他们不称它为 independent names(无依靠名字)。假如,像我一样,你发现术语 "non-dependent" 是一个令人厌恶的东西,你就和我产生了共鸣,但是 "non-dependent" 就是这类名字的术语,所以,像我一样,转转眼睛放弃你的自我主张。)

  nested dependent name(嵌套依靠名字)会导致解析困难。例如,假设我们更加愚蠢地以这种方法开始 print2nd:

  template
  void print2nd(const C& container)
  {
  C::const_iterator * x;
  ...
  }

  这看上去似乎是我们将 x 声明为一个指向 C::const_iterator 的 local variable(局部变量)。但是它看上去如此仅仅是因为我们知道 C::const_iterator 是一个 type(类型)。但是假如 C::const_iterator 不是一个 type(类型)呢?假如 C 有一个 static data member(静态数据成员)碰巧就叫做 const_iterator 呢?再假如 x 碰巧是一个 global variable(全局变量)的名字呢?在这种情况下,上面的代码就不是声明一个 local variable(局部变量),而是成为 C::const_iterator 乘以 x!当然,这听起来有些愚蠢,但它是可能的,而编写 C++ 解析器的人必须考虑所有可能的输入,甚至是愚蠢的。

Tags:箴言 理解 typename

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接