簡體   English   中英

類模板的靜態成員錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM