[英]static member of class template error
我對此代碼段有疑問:
template <typename T>
struct S
{
static int a;
};
template <typename T>
decltype(S<T>::a) S<T>::a;
clang-3.4
說:
s.cpp:8:25: error: redefinition of 'a' with a different type: 'decltype(S<T>::a)' vs 'int'
decltype(S<T>::a) S<T>::a;
^
s.cpp:4:14: note: previous definition is here
static int a;
^
1 error generated.
但是gcc-4.8.2
接受了。 哪個編譯器是對的? 我將來應該避免這樣的代碼嗎?
Clang要求定義在模板定義時匹配聲明,而GCC和其他人推遲匹配直到實例化時間(從來沒有發生過你的例子)。
Clang接受這個:
#include <type_traits>
template <typename T>
struct S
{
static int a;
};
template <typename T>
typename std::enable_if< true, int >::type S<T>::a; // Resolves before instantiation
但拒絕這個小小的變化:
template <typename T>
typename std::enable_if< std::is_same< T, T >::value, int >::type S<T>::a;
我不記得在發生對象聲明匹配時標准規定的位置,但我懷疑Clang是否有權拒絕代碼。 如果我沒記錯的話,標准的意圖是每個聲明只匹配一個定義,並且可以在實例化時間之前確定該映射。
使用GCC顯然適用的更寬松的規則,您可以有兩個成員聲明和兩個定義,但每個定義可以根據模板參數完成任一個聲明。
GCC和MSVC正在接受的代碼是不正確的,不需要診斷......等待在[§3[基本],§7[dcl.dcl],§8[dcl.decl],§14中找到埋藏的實際標准。溫度],或者其他地方。
我仍然無法找到哪些規則將對象定義與前面的聲明匹配,但§14.4/ 2規定decltype(…)
不能與int
等效(我假設在聲明意義上)。
如果表達式e涉及模板參數,則
decltype(e)
表示唯一的依賴類型。 兩個這樣的decltype-specifiers只有在它們的表達式是等價的時才引用相同的類型(14.5.6.1)。 [ 注意:但是,它可能是別名,例如,通過typedef-name。 - 結束說明 ]
我很確定定義匹配聲明需要等效,而不僅僅是別名。 §14.5.6.1深入研究這個領域,除非它專門討論功能簽名。
我認為Clang 可能會拒絕這一點。 關於decltype(e)
14.2p2說
如果表達式e涉及模板參數,則decltype(e)表示唯一的依賴類型。
在DR#2中 ,討論描述說
我的觀點(我認為與最近在反射器上發布的幾個相匹配)是,類外定義必須與模板中的聲明匹配。
...
通常,如果只使用模板中的信息匹配聲明,則聲明有效。
我認為如果其中一個使用typedef(如DR中所示),它仍然匹配,因為S<T>::type
是當前實例化的成員,並且可以直接查找別名類型。 但是,如上所述, decltype(e)
將始終表示唯一類型(在模板分析時間期間),除了指定等效表達式的另一個decltype(e)
。
為什么我說的威力 ? 因為14.6p8
不能為可以生成有效特化的模板發出診斷。
人們可以讀到這一點,因為類型等價檢查只是延遲到實例化之后。 然而,這與我認為的DR中的討論痕跡相矛盾,因為他們說“如果你只能使用模板中的信息來匹配聲明,那么聲明是有效的”(我認為這個聲明的作者意味着在聲明有效的情況下詳盡無遺)。
對我來說,clang在這里打破了。
所有與decltype的組合都將失敗。 沒有decltype它工作。
template <typename T>
struct S
{
static int a;
using type = decltype( a );
typedef decltype( a ) type2;
};
template <typename T>
1) decltype(S<T>::a) S<T>::a;
2) int S<T>::a;
3) typename S<T>::type S<T>::a;
4) typename S<T>::type2 S<T>::a;
1 gcc的作品,clang失敗了
2 gcc + clang的作品
3 gcc作品,clang失敗
4 gcc的作品,clang失敗了
我做了一些嘗試解決問題,但沒有取得任何成功。
關於這類問題還有一些討論: C ++靜態成員初始化(模板內部有趣)
編輯:我發現這個主題在標准中只是“未解決”,直到現在並且clang沒有實現它:看看: http : //clang.llvm.org/cxx_dr_status.html (點205)
我希望我沒有誤解這個頁面。 隨意糾正我的解釋。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.