[英]Name conflict between namespace and class template: different compiler behavior
namespace N
{
namespace Foo
{
template <typename>
struct Foo
{
};
}
}
template <typename Type>
using Foo = N::Foo::Foo<Type>;
namespace N
{
template <typename Type>
struct Bar : Foo<Type>
{
};
}
int main()
{
}
測試編譯器及其編譯標志:
-std=c++14 -Wall -Wextra -Werror -pedantic-errors
-std=c++14 -Wall -Wextra -Werror -pedantic-errors
/EHsc /Za /std:c++14 /permissive-
-std=c++14 -Wall -Werror
匯編結果:
clang ++ :
18 : <source>:18:15: error: expected class name struct Bar : Foo ^
g ++ :成功編譯
vc ++ :
18 : <source>(18): error C2516: 'Foo': is not a legal base class 13 : <source>(13): note: see declaration of 'Foo' 20 : <source>(20): note: see reference to class template instantiation 'N::Bar<Type>' being compiled 18 : <source>(18): error C2143: syntax error: missing ',' before '<'
icc :成功編譯
哪種編譯器行為符合標准?
附加信息:
規范說
在查找基類名稱期間,將忽略非類型名稱([basic.scope.hiding])
名稱是Foo<Type>
,它是一個類型名稱。 名稱N::Foo
不是類型名稱,因此必須將其忽略。 在忽略某些名稱的類似情況下,措辭更明確
如果嵌套名稱說明符中的:: scope resolution運算符前面沒有decltype-specifier,那么查找::之前的名稱只會考慮其特化是類型的名稱空間,類型和模板
這里,當它想要允許type-template<arguments>
時,它不僅會說“類型名稱”或“非類型名稱” 。 但它具體說明了“專業化類型的模板” 。 我認為這種混淆是這里實現分歧的原因。 名稱Foo<Type>
就是我所說的“復合名稱”,因為它包含了嵌套名稱。 因此,可能不清楚其中的哪些確切名稱被忽略,哪些不被忽略。
在查找Foo<Type>
之前查找名稱Foo
。 Foo
的查找不是基類名稱的查找,因此[class.derived] / 2中的查找規則不適用。
參考[basic.lookup.unqual] / 7:
在成員函數體外定義類X的名稱,默認參數,noexcept-specifier,非靜態數據成員的brace-or-equal-initializer,或嵌套類定義25,應在其中一個中聲明。以下方式:
在X類中使用之前或者是X([class.member.lookup])的基類的成員之前,或者
如果X是Y類的嵌套類,在Y中定義X之前,或者應該是Y的基類的成員(此查找依次應用於Y的封閉類,從最內層的封閉類開始),26或
如果X是本地類或是本地類的嵌套類,則在包含X類定義的塊中定義類X之前,或者
如果X是命名空間N的成員,或者是N的成員的類的嵌套類,或者是定義之前的N的成員的函數的本地類中的本地類或嵌套類在命名空間N中的類X或在N的封閉命名空間之一中。
[例如:
namespace M {
class B { };
}
namespace N {
class Y : public M::B {
class X {
int a[i];
};
};
}
// The following scopes are searched for a declaration of i:
// 1) scope of class N::Y::X, before the use of i
// 2) scope of class N::Y, before the definition of N::Y::X
// 3) scope of N::Y's base class M::B
// 4) scope of namespace N, before the definition of N::Y
// 5) global scope, before the definition of N
- 結束例子]
命名空間N
在全局命名空間之前被考慮,因此首先找到N::foo
,這導致程序格式錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.