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

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>
            久久久久网址| 欧美成年人网| 夜久久久久久| 久久偷看各类wc女厕嘘嘘偷窃| 亚洲无人区一区| 欧美国产日韩在线| 欧美不卡视频一区发布| 国产日韩亚洲欧美综合| 一本久道久久综合狠狠爱| 亚洲精品小视频在线观看| 久久久久一区二区| 久久久久一区| 国外成人性视频| 欧美一区二区啪啪| 久久成人精品电影| 国产午夜精品在线| 午夜精品久久一牛影视| 午夜精品www| 国产精品美女黄网| 亚洲淫片在线视频| 久久av最新网址| 国产午夜精品理论片a级大结局 | 欧美黑人在线观看| 欧美激情欧美狂野欧美精品| 一区免费观看| 麻豆精品视频在线观看视频| 麻豆av一区二区三区久久| 国内精品美女av在线播放| 性色av一区二区三区红粉影视| 欧美一区二区视频在线观看2020| 国产精品久久久久999| 亚洲素人一区二区| 欧美在线欧美在线| 国产自产在线视频一区| 久久精品视频亚洲| 亚洲高清久久| 一区二区高清视频| 国产精品极品美女粉嫩高清在线| 一区二区久久久久| 久久国产手机看片| 在线观看三级视频欧美| 欧美福利一区二区| 亚洲素人在线| 久久久综合精品| 亚洲激情电影在线| 欧美日韩在线一二三| 亚洲欧美一级二级三级| 久热精品在线| 一本色道久久综合亚洲精品不| 欧美性事在线| 久久久久久免费| 日韩视频三区| 另类成人小视频在线| 日韩一级欧洲| 国产亚洲欧美日韩美女| 免费在线国产精品| 亚洲无吗在线| 欧美国产另类| 亚洲欧美日韩一区在线| 亚洲第一精品夜夜躁人人躁| 欧美日韩一区二区免费视频| 先锋亚洲精品| 日韩一级精品视频在线观看| 久久久久久久久伊人| 亚洲美女诱惑| 狠狠干狠狠久久| 国产精品老女人精品视频| 久久人人97超碰国产公开结果| 亚洲最新色图| 亚洲二区在线视频| 久久九九国产精品| 亚洲一区二区三区777| 在线精品视频一区二区| 国产精品入口麻豆原神| 欧美大色视频| 久久裸体视频| 欧美一级成年大片在线观看| 日韩视频精品| 亚洲国产精品嫩草影院| 久久久999成人| 亚洲欧美日韩另类| 一区二区欧美日韩| 亚洲日本欧美天堂| 在线精品视频在线观看高清| 国产精品久久久久久亚洲毛片| 欧美不卡三区| 麻豆成人在线观看| 久久久国产精品一区二区中文 | 亚洲黄网站黄| 一区二区三区在线免费观看| 国产精品一二一区| 国产精品v欧美精品v日本精品动漫 | 亚洲欧美日韩国产中文在线| 亚洲精品欧美日韩专区| 亚洲高清av在线| 欲色影视综合吧| 国产中文一区| 国一区二区在线观看| 国产视频精品xxxx| 国产麻豆视频精品| 国产欧美日韩一区二区三区在线观看| 欧美三级在线播放| 欧美日韩在线视频一区二区| 欧美女激情福利| 欧美交受高潮1| 欧美日韩无遮挡| 欧美午夜电影在线| 欧美午夜理伦三级在线观看| 欧美午夜激情小视频| 欧美视频导航| 国产精品久久久久9999高清| 国产精品二区影院| 国产精品一级在线| 国产性色一区二区| 激情一区二区三区| 亚洲国产一成人久久精品| 最新国产成人av网站网址麻豆| 亚洲精品美女在线观看播放| 亚洲美女精品一区| 亚洲午夜未删减在线观看| 午夜精品一区二区三区在线| 久久国产夜色精品鲁鲁99| 久久性色av| 亚洲国产免费看| 中日韩男男gay无套| 午夜国产欧美理论在线播放| 久久黄色影院| 欧美风情在线| 国产精品视频网址| 激情综合亚洲| 一本到12不卡视频在线dvd| 亚洲女性喷水在线观看一区| 久久激情一区| 亚洲黄色一区| 亚洲欧美日韩第一区 | 欧美在线黄色| 免费在线成人av| 国产精品igao视频网网址不卡日韩| 国产精品一区二区在线| 在线精品在线| 亚洲一区二区三区中文字幕在线| 久久国产黑丝| 最新国产乱人伦偷精品免费网站 | 久久综合999| 国产精品高清在线观看| 尤物在线精品| 欧美一区二区免费| 欧美激情综合色| 亚洲一区日韩在线| 欧美国产日韩精品| 国产专区一区| 亚洲与欧洲av电影| 欧美黄污视频| 久久爱www.| 国产精品久久久久久久app| 亚洲大胆av| 久久精品综合| 一区二区三区高清不卡| 玖玖玖免费嫩草在线影院一区| 国产精品日韩精品| 99在线精品观看| 免费看亚洲片| 久久成人精品| 国产老女人精品毛片久久| 一本色道综合亚洲| 欧美成在线视频| 欧美在线视频一区二区| 欧美视频精品在线| 日韩视频中文| 欧美激情视频一区二区三区在线播放| 亚洲男人影院| 国产精品捆绑调教| 亚洲私人黄色宅男| 亚洲精品少妇30p| 欧美国产日韩精品| 最新热久久免费视频| 久久先锋资源| 久久国产精品第一页| 国产日韩一区| 久久激情五月婷婷| 香蕉国产精品偷在线观看不卡| 国产精品福利片| 亚洲一区二区三区成人在线视频精品| 亚洲激情欧美| 欧美精品免费观看二区| 亚洲人被黑人高潮完整版| 欧美www在线| 免费久久99精品国产自| 亚洲高清视频在线| 欧美国产精品人人做人人爱| 老牛影视一区二区三区| 在线观看免费视频综合| 蜜桃av噜噜一区| 六月丁香综合| 亚洲人成网站在线观看播放| 亚洲国产精品视频一区| 欧美精品免费播放| 亚洲无限av看| 亚洲一区二区视频在线| 国产日韩精品综合网站|