C++的嵌套依賴別名(typename的用法)

看了很多遍,還是記錄一下

1、在模板聲明時typename和class是等價的

template<class T> class Widget; // uses "class"
template<typename T> class Widget; // uses "typename"

兩面的兩句等價

2、什麼情況下必須放typename?

template<typename C>
void print2nd(const C& container)
{
    C::const_iterator *x; //①
    ...
}

此時的編譯器會糾結:const_iterator是一個什麼東西?const_iterator是模板參數C內的一個static變量?x是一個全局變量?
再或者:const_iterator是模板參數C內部的一個typedef。假設模板參數C最後用Class_C來實例化,Class_C類似這樣:

class Class_C{
	typedef int const_iterator;
	...
}

那上面的例子中的語句①就是聲明一個指向int類型的指針x,語句①轉化過來就是這樣:

int *x;

程序員是不能讓編譯器糾結的,編譯器糾結的後果是:報錯。程序員嘛,就debug吧。

所以此時我們應該告訴編譯器const_iterator是模板參數C裏面的一個類型。即在C的前面加上typename就可以了,像這樣:

template<typename C>
void print2nd(const C& container)
{
    typename C::const_iterator * x; //①
    ...
}

3、總結一下上面的用法

a、模板內出現的名稱如果依賴於某個模板參數,稱之爲從屬名稱(dependent name)。如果從屬名稱在class內呈嵌套狀,我們稱爲嵌套從屬名稱(nested dependent name)。距離如下:

template<typename C>
void print(const C & container)
{
    C::const_iterator iter(container.begin());
    cout << *iter << endl;
    int value = *iter;
    return;
}
  • 在上述代碼中,iter 是依賴於模板參數C的,因此被稱爲從屬名稱;
  • 同理,value是內置類型,不依賴於任何模板參數,因此被稱爲 非從屬名稱;
  • C++編譯器在面對從屬名稱時,如果此時該從屬名稱又嵌套了其他類型,如此處的 iter就是C::const_iterator類型(嵌套於C類型,從屬於模板參數C)。

b、再來看一個例子:

template<typename C> // typename allowed (as is "class")
void f(const C& container, // typename not allowed
		typename C::iterator iter); // typename required

上述的C並不是嵌套從屬類型名稱 (它並非嵌套與任何“取決於模板參數”的東西內),所以聲明container時並不需要以typename爲前導。
但C::iterator是個嵌套從屬類型名稱,所以必須以typename爲前導。

c、說人話
使用某個模板類裏面typedef的類型時,如果這個類型與模板參數C相關,就需要使用typename。
即這樣的形式:
y(C)::iterator it;
這樣的語句前面就需要前置typename;

參考:
[1] https://blog.csdn.net/gatieme/article/details/50946005
[2] https://blog.csdn.net/xuqingict/article/details/24884811

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章