2016-04-15 3 views
4

Der Code gibt, ist die folgende:Visual C++ Compiler falsche Zeilenreferenz für mehrdeutiges Symbol

namespace n1 
{ 
    template <class T> 
    void n2(); 

    template <class T> 
    void n2(T); 
} 

namespace n2 /* line 12 */ 
{ 
    class c {}; 
} 

using namespace n1; 

namespace n3 
{ 
    void foo(n2::c); 
} 

void n3::foo(n2::c) /* line 24 */ 
{ 

} 

Beim Versuch, es zu kompilieren die neueste Version von Visual C++ Ich erhalte die folgenden Fehler:

1>test.cpp(24): error C2872: 'n2': ambiguous symbol 
1>test.cpp(12): note: could be 'n2' 
1>test.cpp(24): note: or  'n2' 

Die Zeilen 12 und 24 sind im vorherigen Codeteil mit Kommentaren markiert.

Was geht hier vor? Wenn ich die Definition von foo entferne und eine Variable vom Typ n2 :: c außerhalb einer Funktionsargumentliste deklariere, kompiliert es einfach gut. Ich nehme an, weil der Compiler herausfindet, dass ich auf die Klasse und nicht auf irgendeine der Template-Funktionen referenziere . Wenn ich stattdessen die zweite Definition der beiden n2-Template-Funktionen im Namespace n1 lösche, gibt der Compiler mir eine Fehlermeldung, verweist aber auf die richtigen Zeilen: Zeile 12 und die Zeile, wo n2 als Funktion definiert ist (statt Zeile 24)). Ist das ein Compilerfehler?

+0

ich diesen Code mit verschiedenen Compilern getestet haben: VC++ 2015 nicht kompilieren und gibt falsche Zeilennummern aus. VC++ 2012 und 2013 kompilieren nicht, geben jedoch keine Zeilennummern aus (für die Kandidaten). gcc (verschiedene Versionen) kompilieren. - Die Zeilennummern sind eindeutig fehlerhaft (scheint ein neues Feature in VC++ 2015 zu sein), aber ich bin nicht in der Lage zu sagen, ob dieser Code kompilieren sollte oder nicht. –

+0

Niemand hier kann das für dich ändern. Melden Sie Fehler und unerwünschtes Compilerverhalten auf connect.microsoft.com –

Antwort

2

Ich denke, Microsoft ist hier richtig. Unter Angabe der Arbeits C++ Standardentwurf $7.3.4.6, sagt er

If name lookup finds a declaration for a name in two different namespaces, and the declarations do not declare the same entity and do not declare functions, the use of the name is ill-formed....

Dann ist es bei Ihnen ein Beispiel ähnlich gibt, wie folgt aus:

namespace A { 
    class X { }; 
    extern "C" int g(); 
    extern "C++" int h(); 
} 
namespace B { 
    void X(int); 
    extern "C" int g(); 
    extern "C++" int h(int); 
} 
using namespace A; 
using namespace B; 

void f() { 
    X(1);    // error: name X found in two namespaces 
    g();    // OK: name g refers to the same entity 
    h();    // OK: overload resolution selects A::h 
} 

Obwohl beide gcc und Klirren den Code akzeptieren. Ich denke, dass sie hier falsch liegen.

Gehen Sie zurück zum zitierten Absatz und notieren Sie die Zeile "... deklarieren Sie nicht die gleiche Entität und deklarieren Sie keine Funktionen ...". In Ihrem Code ist der Name n2 im Namensraum n1 eine Funktionsvorlage und keine Funktion. Weil eine Funktionsvorlage keine Funktion ist. Siehe $8.3.5.15 (Hervorhebung von mir):

A non-template function is a function that is not a function template specialization. [ Note: A function template is not a function. — end note ]

Ihr Problem zu beheben, qualifizieren n2 mit einem globalen Namensraum ... wie dieses

namespace n1 
{ 
    template <class T> 
    void n2(); 

    template <class T> 
    void n2(T); 
} 

namespace n2 /* line 12 */ 
{ 
    class c {}; 
} 

using namespace n1; 

namespace n3 
{ 
    void foo(::n2::c); 
} 

void n3::foo(::n2::c) /* line 24 */ 
{ 

} 
Verwandte Themen