青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 297,  comments - 15,  trackbacks - 0

[Originally written sometime in December, 2006. Fixed a couple markup errors, changed some wording, and added a little bit 12/23/2007. I still don't quite consider it complete; I haven't explained all the rules yet. I have a ranty version of what I want to add here; start reading where it says "[RESUMING]" if you read this document first.]

The purpose of this document is to describe the reasoning behind the inclusion of the typename keyword in standard C++, and explain where, when, and how it can and can't be used.

A secondary use

There is a use of typename that is entirely distinct from the main focus of this discussion. I will present it first because it is easy. It seems to me that someone said "hey, since we're adding typename anyway, why not make it do this" and people said "that's a good idea."

Most older C++ books, when discussing templates, use the following type of example:

template <class T> ...

I know when I was starting to learn templates, at first I was a little thrown by the fact that T was prefaced by class, and yet it was possible to instantiate that template with primitive types such as int. The confusion was very short-lived, but the use of class in that context never seemed to fit entirely right. Fortunately for my sensibilities, it is also possible to use typename:

template <typename T> ...

This means exactly the same thing as the previous instance. The typename and class keywords can be used interchangeably to state that a template parameter is a type variable (as opposed to a non-type template parameter).

I personally like to use typename in this context because I think it's ever so slightly clearer. And maybe not so much "clearer" as just conceptually nicer. (I think that good names for things are very important.) Some C++ programmers share my view, and use typename for templates. (However, later we will see how it's possible that this decision can hurt readibility.) Some programmers make a distinction between templates that are fully generic (such as the STL containers) and more special purpose ones that can only take certain classes, and use typename for the former category and class for the latter. Others use class exclusively. This is just a style choice.

However, while I use typename in real code, I will stick to class in this document to reduce confusion with the other use of typename.

The real reason for typename

This discussion I think follows fairly closely appendix B from the book C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond by David Abrahams and Aleksey Gurtovoy, though I don't have it in front of me now. If there are any deficiencies in my discussion of the issues, that book contains the clearest description of them that I've seen.

Some definitions

There are two key concepts needed to understand the description of typename, and they are qualified and dependent names.

Qualified and unqualified names

A qualified name is one that specifies a scope. For instance, in the following C++ program, the references to cout and endl are qualified names:

#include <iostream>

int main() {
std::cout %lt;%lt; "Hello world!" %lt;%lt; std:: endl;
}

In both cases, the use of cout and endl began with std::.

Had I decided to bring cout and endl into scope with a using declaration or directive*, they would have been unqualified names, because they would lack the std::.

(* Remember, a using declaration is like using std::cout;, and actually introduces the name cout into the scope that the using appears in. A using directive is of the form using namespace std; and makes names visible but doesn't introduce anything. [12/23/07 -- I'm not sure this is true. Just a warning.])

Note, however, that if I had brought them into scope with using but still used std::cout, it remains a qualified name. The qualified-ness of a name has nothing to do with what scope it's used in, what names are visible at that point of the program etc.; it is solely a statement about the name that was used to reference the entity in question. (Also note that there's nothing special about std, or indeed about namespaces at all. vector<int>::iterator is a nested name as well.)

Dependent and non-dependent names

A dependent name is a name that depends on a template parameter. Suppose we have the following declaration (not legal C++):

template <class T>
class MyClass {
int i;
vector<int> vi;
vector<int>::iterator vitr;

T t;
vector<T> vt;
vector<T>::iterator viter;
};

The types of the first three declarations are known at the time of the template declaration. However, the types of the second set of three declarations are not known until the point of instantiation, because they depend on the template parameter T.

The names T, vector<T>, and vector<T>::iterator are called dependent names, and the types they name are dependent types. The names used in the first three declarations are called non-dependent names, at the types are non-dependent types.

The final complication in what's considered dependent is that typedefs transfer the quality of being dependent. For instance:

typedef T another_name_for_T;

another_name_for_T is still considered a dependent name despite the type variable T from the template declaration not appearing.

Note: I am not very familiar with the notion of dependent types in the type theory sense, but they are not quite the same thing in any case. My impression is that you could probably argue a C++ template itself is a dependent type in the type-theoretical sense, but the C++ notion of a dependent type is more like the argument to a dependent type in the type-theoretical sense.

Some other issues of wording

Note that while there is a notion of a dependent type, there is not a notion of a qualified type. A type can be unqualified in one instance, and qualified the next; the qualification is a property of a particular naming of a type, not of the type itself. (Indeed, when a type is first defined, it is always unqualified.)

However, it will be useful to refer to a qualified type; what I mean by this is a qualified name that refers to a type. I will switch back to the more precise wording when I talk about the rules of typename.

The problem

So now we can consider the following example:

template <class T>
void foo() {
T::iterator * iter;
...
}

What did the programmer intend this bit of code to do? Probably, what the programmer intended was for there to be a class that defined a nested type called iterator:

class ContainsAType {
class iterator { ... }:
...
};

and for foo to be called with an instantiation of T being that type:

foo<ContainsAType>();

In that case, then line 3 would be a declaration of a variable called iter that would be a pointer to an object of type T::iterator (in the case of ContainsAType, int*, making iter a double-indirection pointer to an int). So far so good.

However, what the programmer didn't expect is for someone else to come up and declare the following class:

class ContainsAValue {
static int iterator;
};

and call foo instantiated with it:

foo<ContainsAValue>();

In this case, line 3 becomes a statement that evaluates an expression which is the product of two things: a variable called iter (which may be undeclared or may be a name of a global) and the static variable T::iterator.

Uh oh! The same series of tokens can be parsed in two entirely different ways, and there's no way to disambiguate them until instantiation. C++ frowns on this situation. Rather than delaying interpretation of the tokens until instantiation, they change the languge:

Before a qualified dependent type, you need typename

To be legal, assuming the programmer intended line 3 as a declaration, they would have to write

template <class T>
void foo() {
typename T::iterator * iter;
...
}

Without typename, there is a C++ parsing rule that says that qualified dependent names should be parsed as non-types even if it leads to a syntax error. Thus if there was a variable called iter in scope, the example would be legal; it would just be interpreted as multiplication. Then when the programmer instantiated foo with ContainsAType, there would be an error because you can't multiply something by a type.

typename states that the name that follows should be treated as a type. Otherwise, names are interpreted to refer to non-types.

This rule even holds if it doesn't make sense even if it doesn't make sense to refer to a non-type. For instance, suppose we were to do something more typical and declare an iterator instead of a pointer to an iterator:

template <class T>
void foo() {
typename T::iterator iter;
...
}

Even in this case, typename is required, and omitting it will cause compile error. As another example, typedefs also require use:

template <class T>
void foo() {
typedef typename T::iterator iterator_type;
...
}

from:
http://pages.cs.wisc.edu/~driscoll/typename.html
posted on 2010-04-19 11:58 chatler 閱讀(483) 評論(0)  編輯 收藏 引用 所屬分類: Template
<2025年12月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

常用鏈接

留言簿(10)

隨筆分類(307)

隨筆檔案(297)

algorithm

Books_Free_Online

C++

database

Linux

Linux shell

linux socket

misce

  • cloudward
  • 感覺這個博客還是不錯,雖然做的東西和我不大相關,覺得看看還是有好處的

network

OSS

  • Google Android
  • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
  • os161 file list

overall

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲人成在线观看一区二区| 99国产欧美久久久精品| 午夜视频在线观看一区| 一本大道久久a久久综合婷婷| 欧美成人激情视频| 亚洲精品偷拍| 一区二区日本视频| 国产日韩欧美精品一区| 久久男女视频| 欧美成人小视频| 一本大道久久a久久精品综合| 亚洲美女91| 国产精品一区二区在线| 久久只精品国产| 欧美国产一区二区| 亚洲免费在线电影| 久久精品国产久精国产一老狼| 在线观看日韩| 夜夜嗨av一区二区三区| 国产婷婷色一区二区三区四区| 久热精品视频在线| 欧美精品久久久久a| 久久婷婷成人综合色| 久久露脸国产精品| 在线亚洲自拍| 欧美在线观看www| 亚洲人成网站精品片在线观看 | 欧美午夜精品理论片a级按摩| 亚洲免费一区二区| 久久综合中文| 性做久久久久久免费观看欧美| 久久久水蜜桃| 亚洲专区国产精品| 久久综合五月| 午夜精品99久久免费| 母乳一区在线观看| 欧美影院成人| 欧美日韩亚洲一区在线观看| 葵司免费一区二区三区四区五区| 欧美日韩dvd在线观看| 美女尤物久久精品| 国产精品视频久久| 亚洲精品影院| 亚洲国产精品精华液2区45| 亚洲性色视频| 99视频有精品| 欧美成人午夜| 蜜臀99久久精品久久久久久软件| 国产精品久久久久久模特| 亚洲成在线观看| 国产夜色精品一区二区av| 一区二区动漫| 亚洲视频精选在线| 欧美国产大片| 亚洲大胆人体在线| 亚洲成色精品| 久久九九免费视频| 久久亚洲春色中文字幕| 国产精品一卡| 亚洲影视在线播放| 亚洲女性喷水在线观看一区| 欧美激情一区二区久久久| 欧美电影资源| 亚洲国产欧美另类丝袜| 久久久久国产精品厨房| 久久人人爽人人爽爽久久| 国产一区二区在线观看免费播放| 亚洲性图久久| 久久精品国产在热久久| 国产视频一区在线观看一区免费| 亚洲图片欧洲图片av| 亚洲欧美日韩高清| 国产精品人成在线观看免费 | 亚洲高清中文字幕| 亚洲啪啪91| 欧美欧美午夜aⅴ在线观看| 亚洲欧洲综合另类| 在线一区观看| 国产精品一区二区a| 午夜精品在线看| 老司机凹凸av亚洲导航| 亚洲二区免费| 欧美激情女人20p| 夜夜嗨av一区二区三区四季av| 亚洲图片欧美午夜| 国产情侣久久| 狼狼综合久久久久综合网| 亚洲国产欧美在线人成| 亚洲一区在线观看免费观看电影高清| 国产精品jizz在线观看美国| 午夜国产精品影院在线观看| 久久久99爱| 亚洲开发第一视频在线播放| 欧美日韩综合另类| 久久se精品一区二区| 欧美激情一区二区| 亚洲欧美日韩一区二区在线 | 欧美日韩免费观看一区二区三区| 日韩视频免费大全中文字幕| 欧美影院成年免费版| 亚洲电影免费观看高清完整版在线| 欧美激情一二三区| 欧美亚洲一区二区在线| 欧美高清视频在线 | 亚洲国产日韩欧美在线99| 免费亚洲一区二区| 亚洲一区亚洲| 亚洲高清成人| 久久久久久久久久久成人| 99国产精品久久久久久久久久| 国产欧美综合一区二区三区| 欧美国产精品专区| 欧美一区二区三区免费在线看| 亚洲国产婷婷香蕉久久久久久99| 欧美一区二区| 99亚洲一区二区| 在线观看一区二区精品视频| 国产精品成人观看视频免费| 快she精品国产999| 香蕉成人久久| 亚洲婷婷综合久久一本伊一区| 欧美黄色一区二区| 久久夜色精品国产欧美乱极品| 宅男噜噜噜66一区二区| 亚洲黄色大片| 激情成人综合网| 国产美女精品视频| 国产精品av免费在线观看| 欧美va天堂| 久久婷婷影院| 久久国产精品久久久久久| 亚洲一区高清| 在线亚洲成人| 亚洲最黄网站| 99亚洲一区二区| 亚洲日本va午夜在线电影| 欧美www视频在线观看| 久久综合99re88久久爱| 久久九九全国免费精品观看| 午夜精品美女自拍福到在线| 在线中文字幕不卡| 日韩一级精品| 一本色道久久综合亚洲二区三区| 亚洲国产一区二区在线| 亚洲承认在线| 亚洲欧洲日本专区| 亚洲精品少妇网址| 日韩亚洲一区二区| 一本在线高清不卡dvd| 日韩系列在线| 亚洲宅男天堂在线观看无病毒| 亚洲一区二区在线播放| 亚洲网站视频| 欧美在线观看网站| 久久国产一区二区| 久久久噜噜噜久久中文字幕色伊伊| 久久久99免费视频| 美国成人直播| 亚洲国产另类精品专区| 亚洲狠狠婷婷| 亚洲午夜精品国产| 午夜精品久久久久久久| 久久精品国产精品亚洲综合| 老司机免费视频一区二区| 欧美黄污视频| 国产精品无码永久免费888| 国产在线日韩| 亚洲激情视频| 亚洲制服少妇| 可以免费看不卡的av网站| 亚洲国产精品一区二区www在线| 亚洲国产日日夜夜| 亚洲小说春色综合另类电影| 欧美在线网站| 欧美另类videos死尸| 国产欧美精品xxxx另类| 在线观看日韩一区| 亚洲一区在线播放| 欧美成人免费在线观看| 日韩一区二区久久| 久久精品伊人| 欧美色欧美亚洲另类二区| 黄色成人在线观看| 在线亚洲欧美| 女仆av观看一区| 亚洲自啪免费| 欧美激情视频一区二区三区不卡| 国产精品你懂的在线欣赏| 亚洲欧洲在线一区| 久久大逼视频| 亚洲精品影院| 久久综合国产精品台湾中文娱乐网| 欧美精品日韩综合在线| 激情成人av在线| 午夜精品视频在线| 亚洲国产视频a| 久久久免费精品| 国产精品一级| 亚洲欧美国产毛片在线| 亚洲国产精品一区二区久|