c++ - 模板中關鍵字“typename”和“class”的區別?


對於模板,我已經看到這兩個聲明:

template < typename T >
template < class T >

有什麼不同?

在下面的例子中,這些關鍵字究竟意味著什麼(摘自德國維基百科有關模板的文章)?

template < template < typename, typename > class Container, typename Type >
class Example
{
     Container< Type, std::allocator < Type > > baz;
};


Answers


在指定模板的基本情況下, typenameclass是可以互換的:

template<class T>
class Foo
{
};

template<typename T>
class Foo
{
};

是等同的。

話雖如此,有些情況下, typenameclass是有區別的。

第一個是依賴類型的情況。 typename用於聲明何時引用依賴於另一個模板參數的嵌套類型,如本例中的typedef

template<typename param_t>
class Foo
{
    typedef typename param_t::baz sub_t;
};

第二個你真的在你的問題中顯示,但你可能沒有意識到:

template < template < typename, typename > class Container, typename Type >

當指定一個模板模板時 ,必須像上面那樣使用class關鍵字 - 在這種情況下它不能typename互換(注意:因為在這種情況下C ++ 17兩個關鍵字都是允許的)

明確實例化模板時,還必須使用class

template class Foo<int>;

我相信還有其他一些我錯過的例子,但底線是:這兩個關鍵字是不相同的,這些是一些常見的情況下,你需要使用一個或另一個。




為了命名模板參數, typenameclass是等價的。 §14.1.2:

模板參數中的類和類型名稱之間沒有語義上的區別。

然而,在使用模板的時候,在另一個上下文中可以使用typename來提示編譯器引用了依賴類型。 §14.6.2:

除非可用的名稱查找找到類型名稱或名稱由關鍵字typename限定,否則假定在模板聲明或定義中使用的名稱(取決於模板參數)不會命名類型。

例:

typename some_template<T>::some_type

如果沒有typename那麼編譯器通常不能說明你是否指向一個類型。




雖然沒有技術上的差異,但我曾經看到這兩個用來表示略有不同的東西。

對於應該接受任何類型為T的模板,包括內置插件(如數組)

template<typename T>
class Foo { ... }

對於僅在T是真實類的地方使用的模板。

template<class T>
class Foo { ... }

但請記住,這純粹是一些人使用的風格。 不是由標準強製或由編譯器強制執行




  1. 沒有不同
  2. 模板類型參數Container本身是一個具有兩個類型參數的模板。



這段代碼是從C ++的入門書。 雖然我相信這是錯誤的。

每個類型參數必須以關鍵字class或typename開頭:

// error: must precede U with either typename or class
template <typename T, U> T calc(const T&, const U&);

這些關鍵字具有相同的含義,可以在模板參數列表中互換使用。 模板參數列表可以使用兩個關鍵字:

// ok: no distinction between typename and class in a template parameter list
template <typename T, class U> calc (const T&, const U&);

使用關鍵字typename而不是class來指定模板類型參數似乎更直觀。 畢竟,我們可以使用內置(非類)類型作為模板類型參數。 而且,typename更清楚地表明下面的名字是一個類型名稱。 但是,在模板已經被廣泛使用之後,typename被添加到了C ++中。 一些程序員繼續單獨使用類