2015-09-25 37 views
5

考慮代碼:錯誤時明確地將模板非類型參數

class Base{}; 
class Derived: public Base{}; 

template<Base& b> // references (and pointers) can be used as non-types 
void f(){} 

int main() 
{ 
    Derived d; 
    // f(d); // Error, template type must match exactly 
    f<(Base&)d>(); // Error here, why?! 
} 

我明白爲什麼評論調用失敗:模板類型必須完全匹配。但是我嘗試在第二個電話打石膏,並得到這個錯誤(gcc5.2):如果我做Derived d;全球

error: 'd' is not a valid template argument for type 'Base&' because it is not an object with external linkage

同樣的錯誤。鏗鏘有點更有幫助,說

... note: candidate template ignored: invalid explicitly-specified argument for template parameter 'b'

我的問題是:是否代碼上面的法律或不?如果不是,有什麼理由爲什麼?

回答

4

此答案假定C++ 11或更高

兩個問題這裏:

1)任何派生到基轉換爲非類型模板參數[temp.arg。無類型]/P1

For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):

— a subobject (1.8),

2)該對象的地址應該是在編譯時間。總結[temp.arg.nontype]/p1[expr.const]/p5因此它應該有static storage duration

把這兩點結合起來,你就會有以下編譯

class Base{}; 
class Derived: public Base{}; 

template<Base& b> // references (and pointers) can be used as non-types 
void f(){} 

Base obj; // Static storage duration 

int main() 
{ 
    f<obj>(); 
} 

Live Example

+0

另請參閱http://stackoverflow.com/questions/5687540/non-type-template-parameters – DrWatson

2

從[temp.arg.nontype]:

A template-argument for a non-type template-parametershall be a converted constant expression (5.20) of the type of the template-parameter.

有這裏有兩個問題。首先,d沒有鏈接,因此您不能在常量表達式中引用它。這是一個簡單的修復,但:

Derived d; 
int main() { 
    f<d>(); // still an error 
} 

現在,我們有另一個問題。我們進入下一句:

For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):
(1.1) — a subobject (1.8),

我們正在試圖採取引用的Derived子對象(基類子對象)。無論連接如何,這都被明確禁止。