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

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 閱讀(471) 評論(0)  編輯 收藏 引用 所屬分類: Template
<2025年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

常用鏈接

留言簿(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>
            亚洲自拍电影| 亚洲欧美日韩在线播放| 亚洲精品日韩精品| 国产精品美女| 国产美女诱惑一区二区| 宅男噜噜噜66一区二区| 亚洲自拍另类| 午夜视频在线观看一区二区| 国产色综合久久| 久久久之久亚州精品露出| 亚洲成色www久久网站| 欧美亚洲在线视频| 老司机精品福利视频| 亚洲国产欧美日韩精品| 亚洲一区视频在线观看视频| 亚洲制服欧美中文字幕中文字幕| 亚洲福利视频二区| 亚洲午夜高清视频| ●精品国产综合乱码久久久久 | 久久一综合视频| 99国产精品久久| 国产一区观看| 欧美精品在线一区二区三区| 亚洲免费视频在线观看| 亚洲大胆人体在线| 99视频超级精品| 亚洲国产精品一区二区www在线| 日韩小视频在线观看| 欧美大片在线观看一区| 久久国产66| 亚洲欧美国产制服动漫| 久久综合导航| 亚洲天堂av综合网| 亚洲制服丝袜在线| 亚洲片区在线| 欧美成年人视频网站| 欧美亚洲三级| 欧美在线观看视频一区二区| 亚洲一区二区三区精品视频| 久久免费观看视频| 久久精品久久99精品久久| 欧美一级片在线播放| 欧美激情第一页xxx| 欧美成人精品一区| 亚洲永久在线| 欧美在线关看| 性伦欧美刺激片在线观看| 午夜久久美女| 欧美三区在线视频| 国产精品成人一区二区艾草| 亚洲无线视频| 欧美日韩三级电影在线| 欧美视频在线免费看| 午夜精品电影| 久久综合九色综合欧美狠狠| 野花国产精品入口| 亚洲欧美视频在线| 国产精品自在在线| 午夜国产精品视频| 亚洲一区二区av电影| 欧美午夜片在线观看| 国产精品成人久久久久| 日韩一级不卡| 亚洲国产老妈| 欧美激情一区二区| 欧美激情精品久久久久久久变态 | 久久天天躁狠狠躁夜夜av| 亚洲小说欧美另类婷婷| 国产精品久久一级| 欧美亚洲视频在线看网址| 亚洲一区二区久久| 国产亚洲永久域名| 日韩视频一区二区在线观看 | 欧美四级剧情无删版影片| 夜夜嗨av色一区二区不卡| 午夜国产精品视频免费体验区| 亚洲综合不卡| 国外成人在线视频网站| 精久久久久久| 这里只有精品视频在线| 午夜免费久久久久| 欧美一区二区三区四区在线观看地址| 国产欧美日韩三级| 日韩午夜中文字幕| 亚洲作爱视频| 精品999日本| 亚洲黑丝在线| 国产欧美一区二区三区在线老狼| 久久精品噜噜噜成人av农村| 老司机免费视频久久| 亚洲视频在线二区| 亚洲第一中文字幕| 欧美视频在线看| 久热综合在线亚洲精品| 亚洲免费一区二区| 亚洲国产日韩一区| 久久久久久91香蕉国产| 中日韩午夜理伦电影免费| 国产欧美丝祙| 久久久久久久久久久久久9999| 蜜臀av性久久久久蜜臀aⅴ四虎| 国产精品v欧美精品v日本精品动漫 | 亚洲深夜福利视频| 久久五月天婷婷| 亚洲视屏在线播放| 国模私拍视频一区| 一区二区三区欧美| 欧美大片在线观看| 亚洲国产精品一区二区www| 亚洲欧美日韩在线不卡| 久久久精品视频成人| 国产日韩欧美视频| 亚洲日本理论电影| 在线观看亚洲视频| 久久人体大胆视频| 欧美色中文字幕| 亚洲福利久久| 亚洲成人在线网| 校园春色综合网| 亚洲专区免费| 欧美日韩999| 亚洲小说欧美另类社区| 久久久久久欧美| 亚洲国产精品成人va在线观看| 99精品黄色片免费大全| 亚洲精品网站在线播放gif| 久久精品一区二区三区不卡| 欧美一区日本一区韩国一区| 欧美日韩一区国产| 亚洲精品日韩在线观看| 欧美激情一区在线| 欧美成人在线免费观看| 国产婷婷97碰碰久久人人蜜臀| 一区二区高清视频在线观看| 亚洲区欧美区| 亚洲综合视频网| 欧美一区二区三区四区在线观看地址 | 免费一区视频| 99re66热这里只有精品3直播| 久久久久久日产精品| 久久免费高清| 在线欧美视频| 久久亚洲影院| 亚洲国产一二三| 日韩亚洲精品在线| 欧美日韩在线免费视频| 亚洲久久一区| 亚洲自拍偷拍网址| 国产欧美日韩一区二区三区| 欧美与欧洲交xxxx免费观看 | 亚洲美女区一区| 一卡二卡3卡四卡高清精品视频| 一区二区免费看| 午夜久久久久| 激情久久久久久| 欧美a级理论片| 99riav1国产精品视频| 亚洲一区二区黄色| 国产欧美在线观看| 久久久久成人精品| 亚洲欧洲一区二区天堂久久| 国产日韩视频| 久久精品论坛| 亚洲激情国产| 欧美在线免费视屏| 国产精品99久久久久久白浆小说| 夜夜嗨av一区二区三区四季av| 麻豆av一区二区三区| 亚洲国产高清一区二区三区| 在线综合亚洲| 国产一级久久| 美女精品一区| 亚洲午夜精品网| 欧美韩日一区二区三区| 亚洲一区二区三区在线视频| 国产午夜精品久久久| 欧美成人dvd在线视频| 日韩午夜精品视频| 久久久久综合网| 中文日韩欧美| 亚洲高清不卡| 国产日本亚洲高清| 欧美精品七区| 久久国产视频网| 亚洲欧美日韩在线高清直播| 韩日欧美一区二区三区| 欧美视频中文在线看| 麻豆成人精品| 香蕉乱码成人久久天堂爱免费 | 国产精品99久久不卡二区| 国产日韩在线播放| 欧美日韩一区二区三区| 久久精品1区| 亚洲一区二三| av成人免费观看| 亚洲国产成人在线播放| 久久精品最新地址| 亚洲视屏在线播放| 99re热精品| 亚洲精品一二区|