2017-03-08 15 views
7

當指定一個模板類時,爲什麼要求<>有一個很好的理由,該模板類具有所有模板參數的默認值?爲什麼在指定一個模板類時需要<>,該模板類具有所有模板參數的默認值?

例如

#include <iostream> 

template<typename T = int> 
class C { 
public: 
    T obj = 0; 
}; 

int main() 
{ 
    C c1; // Error on almost all compilers (see note below) 
    C<> c2; 
    std::cout << c1.obj << " " << c2.obj << std::endl; 
    return 0; 
} 

這方面的一個例子缺點是,如果你有這已經是在不同的地方使用了類,你以後重構它與它的模板參數默認參數類模板,那麼你就必須添加<>在所有使用該類的地方。

注意:它看起來像GCC最新HEAD(7.0.1)accepts的語法沒有<>。早期版本不會,任何版本的Clang都不會。這是最新的GCC HEAD中的錯誤嗎?或者,也許C++ 17的標準現在接受沒有<>的語法,GCC就在這裏?

+1

'C c1 {};'編譯最新的clang。 –

+1

[This answer](http://stackoverflow.com/a/16015037/598696)解釋了爲什麼你需要'<>' - 簡而言之,它是爲了避免模板和類型之間的不確定性。 –

+3

*「或者,也許C++ 17的標準現在接受沒有<>」*的語法,在C++ 17中有類模板扣除發生在這裏 –

回答

4

在C++中17,這是公形成:

C c1{}; 

由於deduction for class templates。我們會綜合每個構造函數(和演繹指南)的功能,並執行重載解析:

template <class T=int> C<T> foo(); 
template <class T=int> C<T> foo(C<T> const&); 
template <class T=int> C<T> foo(C<T>&&); 

第一個是一個可行的過載,而其他兩個都沒有,所以扣成功,佔位符C被替換由推斷類型C<int>

然而,語法,一個初始化是需要在[dcl.type.class.deduct]

如果推斷的類類型的佔位符作爲DECL說明符出現DECL說明符-SEQ一個簡單聲明,該聲明的INIT說明符應的形式爲:

說明符-ID屬性說明符-SEQ選擇初始化

佔位符是通過重載類 模板扣(13.3.1.8)所選擇的函數的返回類型替換。

C c;不含初始化,所以它不適合語法。這是允許這個的gcc錯誤。雖然具體禁止這一點似乎很奇怪。顯然,這個限制已經在Kona中解除了,因此C c;確實會在C++ 17中形成。一旦新的措詞出來,我會更新答案。


在C++ 17之前,聲明是不合格的,因爲C不是一個類型。 CC<>不是一回事。對於擁有所有默認的模板參數,現在仍然沒有特別的考慮。類型和類模板是不同的,並繼續以不同的方式處理。

+0

根據http://en.cppreference.com/w/cpp/language/class_template_deduction對變量聲明的推導應該只發生在「使用直接加括號或大括號初始值設定項」時,所以也許最新的Clang是不接受'C c1;'但只有'C c1 {};',而最新的GCC也接受前者是錯誤的。 – Danra

+0

@Danra是的,初始化是必需的,已更新。 – Barry

+0

所以'C c {};'是有效的,它匹配哪個函數調用:'foo()'或'foo({})'? –

相關問題