簡體   English   中英

命名空間和類模板之間的名稱沖突:不同的編譯器行為

[英]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()
{
}

測試編譯器及其編譯標志:

  • clang ++ 5.0.0-std=c++14 -Wall -Wextra -Werror -pedantic-errors
  • g ++ 7.2-std=c++14 -Wall -Wextra -Werror -pedantic-errors
  • vc ++ 19.10.25017 (VS 2017): /EHsc /Za /std:c++14 /permissive-
  • icc 18.0.0-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.

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