2013-12-23 12 views
8

Kann mir jemand helfen zu verstehen, ist das richtige Verhalten oder nicht.Mehrdeutiger Fehler mit char * und char [N]

Betrachten Sie dieses Beispiel:

#include <iostream> 
using namespace std; 

template <typename T> 
struct test { 
}; 

template <typename T> 
bool operator==(const test<T>& obj, const T* arr) { 
    return true; 
} 

template <typename T, size_t TN> 
bool operator==(const test<T>& obj, const T (&arr)[TN]) { 
    return false; 
} 

int main() { 
    cout << (test<char>() == "string") <<endl; 
    return 0; 
} 

mit gcc 4.7.3 es wie erwartet nur gut und gibt '0' kompiliert.

Aber mit Visual Studio Compiler meldet es eine ambiguous error (C2593).

Wer hat Recht in dieser Situation und was sagt standard darüber?

Vielen Dank.

+1

Es ist mehrdeutig, denke ich. – Shoe

Antwort

4

Die Verwendung ziemlich neuer Versionen (d. H. Neuerer Köpfe der Entwicklungszweige) von gcc und clang zeigen ebenfalls eine Mehrdeutigkeit. Ich hätte gedacht, dass die Überladung, die ein Array nimmt, besser ist, aber es scheint, dass der Code mehrdeutig ist. Ich habe jedoch die relevanten Klauseln im Standard noch nicht aufgespürt.

+2

+1 Ich bin ziemlich sicher, dass es durch 14.8.2.4 '[temp.deduct.partial]' und 14.5.6.2 '[temp.func.order]' gesteuert wird. Zu sagen, dass diese Abschnitte des Standards "fleischig" sind, wäre eine grobe Untertreibung von epischen Proportionen. Nichtsdestoweniger habe ich eine ähnliche Frage beantwortet, indem ich tatsächlich diese Beinarbeit gemacht habe (kann mich jetzt nicht daran erinnern) und glaube, dass du richtig bist, also +1. – WhozCraig

+3

Der entscheidende Punkt ist, dass der Rang der Identitäts- und Array-zu-Zeiger-Konvertierungen derselbe ist: * Exakte Übereinstimmung *, sodass keine der Konvertierungssequenzen (keine Konvertierung/Array zu Zeiger) schlechter ist als die andere. –

1

Wie ich verstehe, funktioniert das einfache Überladen in neuen Versionen von gcc nicht und funktioniert bereits in VC10 nicht.

Also, wenn jemand fragt, wie dieses Problem zu beheben ist hier eine Lösung:

template <typename T> 
struct test { 
}; 

template <typename T> 
struct parse { 
}; 

template <typename T> 
struct parse<T*> { 
    static bool run() { 
     return true; 
    } 
}; 

template <typename T, size_t TN> 
struct parse<T[TN]> { 
    static bool run() { 
     return false; 
    } 
}; 

template <typename T, typename T2> 
bool operator==(const test<T>& obj, const T2& obj2) { 
    return parse<T2>::run(); 
} 

int main() { 
    cout << (test<char>() == "string") <<endl; 
    cout << (test<char>() == (char*)"string") <<endl; 
    return 0; 
} 

Zusammengestellt es mit VC10, gcc-4.6.3 und gcc-4.8.1. Scheint korrekt zu funktionieren.