2015-05-21 80 views
2

我見過以下預C++ 11碼的朋友類模板,作爲一個伎倆來聲明類模板的朋友聲明通過包裝

template <typename T> 
struct Wrapper 
{ 
    typedef T type; 
}; 

template <typename T> 
class Foo 
{ 
    friend class Wrapper<T>::type; // effectively makes T a friend 
}; 

struct Test{}; 

int main() 
{ 
    Foo<Test> foo; 
} 
(在C++ 11可以簡單地用 friend T;完成)

代碼編譯上克細++(4.9/5.1/6),但在鐺失敗++(3.5/3.6/3.7),並顯示錯誤

error: elaborated type refers to a typedef

friend class Wrapper::type;

是上述標準兼容,即,代碼有效或不?

+0

相關:http://stackoverflow.com/questions/21952658/type-dependent-nested-name-specifier-in-elaborated-type-specifier – 0x499602D2

+0

或http://stackoverflow.com/questions/14623338/elaborated-type-refers-to-typedef-error-when-trying-to-befriend-a-typedef –

回答

1

§7.1.6.3/ 2:

If the identifier resolves to a typedef-name or the simple-template-id resolves to an alias template specialization, the elaborated-type-specifier is ill-formed.

0

這不符合規定。在[class.friend]/3 friend語法規則是:

A friend declaration that does not declare a function shall have one of the following forms:

friend elaborated-type-specifier ; 
friend simple-type-specifier ; 
friend typename-specifier ; 

class Wrapper<T>::type是無那些說明符類型。它不是闡述型說明符,因爲Wrapper<T>::type不是標識符類名稱,而且顯然不是其他兩個之一。你正在尋找簡單地說就是:

friend typename Wrapper<T>::type; 
+0

'朋友類 - 鍵嵌套名稱說明符標識符;'是允許7.1.6.3 – Columbo

+0

@Columbo嗯,你是對的。似乎不一致? – Barry

+0

@Columbo所以如果'包裝 ::類型'是一些實際類型,而不是別名,你可以做'朋友類包裝 :: type'?爲什麼允許一個類型而不是別名? – Barry

0

[dcl.typedef]/P8:

[ Note: A typedef-name that names a class type, or a cv-qualified version thereof, is also a class-name (9.1)

If a typedef-name is used to identify the subject of an elaborated-type-specifier (7.1.6.3), a class definition (Clause 9), a constructor declaration (12.1), or a destructor declaration (12.4), the program is ill-formed. — end note ] [Example:

struct S { 
    S(); 
    ~S(); 
}; 

typedef struct S T; 
S a = T(); // OK 
struct T * p; // error 

end example ]

的代碼應該在模板實例化時,它這樣做正確的鏘失敗。

使用typename代替struct允許代碼在兩個編譯器中傳遞。

+0

那麼,這是一個說明;不規範。 – Columbo