![](/img/trans.png)
[英]Strange template compile errors: is this a g++ bug, a Clang bug, or...?
[英]Certain errors in uninstantiated template not reported by g++
考慮以下示例:
class A
{
void foo();
public:
void bar();
};
template <class> class B
{
B()
{
A a;
a.foo(); // 1
A::bar(); // 2
a.bar(1); // 3
}
};
注意B
從未實例化。
clang++
報告所有三個標記的行都是錯誤的。 g++
(4.8.3)接受第1
行和第2
,僅報告第3
行。
如果實例化了B
,則g++
高興地將所有三行報告為錯誤。
這是g++
錯誤嗎? 有人會這樣想。 A
不是從屬名稱,應在模板定義時正常檢查其成員。 有沒有我看不到的細微差別?
這些預實例化消息不是由標准強制執行的,而是由編譯器決定的
n3337§14.6-8
不得針對可為其生成有效專業化的模板定義發布診斷。 如果無法為模板定義生成有效的專業化名稱,並且未實例化該模板,則該模板定義格式錯誤, 無需診斷。
重點礦
通常無法判斷a.foo();
是否a.foo();
或A::bar();
在模板定義時是一個錯誤,即使對於A::foo
和A::bar
那些特定定義也是如此。
一般來說, a.foo();
如果A
作為朋友有B<T>
某些特化,而沒有其他特化,則可能是有效的,這會使有效性取決於模板參數。
一般來說, A::bar();
如果B<T>
直接或間接將A
作為基類,並且模板類通常在模板定義時尚不知道其基類,則可能有效。
即使可以在此處檢測到這兩種方法都不可行( A
沒有朋友,而B<T>
沒有鹼),也需要付出很大的努力才能獲得很少的收益。 因此,僅在實例化時簡單地執行此類檢查就很有意義,這就是GCC采取的方法。
實際上,在C ++中沒有規則要求在模板定義時對此進行診斷(正如Marco A.的答案正確指出的那樣)。 僅當實例化模板時,模板定義中的任何錯誤才會使程序按照2.2p1項目符號要點8的形式出現格式錯誤,並需要進行診斷:
如果任何實例化失敗,則程序的格式不正確。
在您的程序中,沒有實例化,因此沒有失敗的實例化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.