Frage

Bitte beachten Sie diesen Code:

template<typename T>
char (&f(T[1]))[1];

template<typename T>
char (&f(...))[2];

int main() { char c[sizeof(f<void()>(0)) == 2]; }

Ich erwartete es SFINAE und chosing die zweite Überlast, da die Substitution von T in T[1] Ausbeuten

tun
 void [1]()

Welche ist ein ungültiger Typ, natürlich. Anpassung der Parametertypen (Array-> Zeiger) erfolgt nach Template-Parameter in Funktionsparameter ersetzt und die Überprüfung für gültig resultierenden Typen wie 14.8.2 [temp.deduct] beschreibt.

Aber beide comeau und GCC scheitern die oben zu kompilieren. Sowohl mit unterschiedlicher Diagnostik.

Comeau sagt:

  

"ComeauTest.c", Zeile 2: Fehler: Anordnung von Funktionen ist nicht erlaubt char (&f(T[1]))[1];

GCC sagt (Version 4.3.3):

  

Fehler: ISO C ++ verbietet Null-size Array c

Bedeutung, hat GCC nicht zu ersetzen scheitern, aber es wählt die erste Überlastung der f, eine sizeof von 1 zurückkehrt, statt andernfalls es vorne wie Comeau substituieren.

Welche Compiler ist richtig und ist mein Code überhaupt gültig? Bitte beachten Sie oder geben Sie den richtigen Standard-Abschnitt in Ihrer Antwort. Dank!


Aktualisieren : Die Norm enthält selbst ein solches Beispiel in der Liste 14.8.2/2. Ich weiß nicht, warum ich es übersehen zuerst:

template <class T> int f(T[5]);
int I = f<int>(0);
int j = f<void>(0); // invalid array

Während das Beispiel nur informativ ist, zeigt es die Absicht, alle jene geheimnisvollen Absätzen und scheint den Code zu zeigen, oben sollte die erste Überlast arbeiten und ablehnen.

War es hilfreich?

Lösung

Ein kleiner Hinweis, wenn auch sehr selten, habe ich einige Gelegenheiten gefunden, wo ich glauben, dass die Comeau Compiler es falsch ist - obwohl diese Gelegenheiten sind so selten, dass es ist immer wert doppelt und dreifach Überprüfen Sie Ihre Annahmen!

Ich habe einen Grund für das Verhalten von g ++ kann. Ich bin nicht sicher, ob seine angegeben, wann genau Parametertypen eingestellt:

Beachten Sie Folgendes:

template<typename T>
struct A
{
  void bar (T[10]);
};

template<typename T>
void A<T>::bar (T*)
{
}

Die Definition von 'bar' legal ist, als "T [10]" zerfällt "T *" an. ich mache nichts sehen in der Norm, die den Compiler verbietet die Anpassung von 8.3.5 gegen die Template-Deklaration durchgeführt wird, und es verbessert auch die Leistung, wenn es darum geht, Anpassung zu überlasten.

Angewandt auf Ihr Beispiel g ++ könnte es als Behandeln:

template<typename T>
char (&f( T* ))[1];

template<typename T>
char (&f(...))[2];

int main() { char c[sizeof(f<void()>(0)) == 2]; }

In dem obigen, der substituierten Parameter ist ein Zeiger auf Recht Funktion, anstatt eine Reihe von Funktionen.

Also, für mich ist die Frage - ist, wenn es etwas, das prohibts die Anpassung für die Funktionsparameter (8.3.5) zweimal?

Ich persönlich denke, dass es Sinn macht, die Anpassungen geschehen zu lassen zweimal da sonst erschwert es die Anpassung der Funktionsvorlage Überlastungen

Abschließend denke ich, seine Gültigkeit für g ++ die erste Überlastung wählen je nachdem, wie es treates Array-Parameter verfallen, und Comeau ist falsch kein Abzug Ausfall für die Anordnung von Funktionen zu haben.

Natürlich bedeutet dies nun, dass (wenn Comeau fixiert wurde) dann jeden Compiler wählen würde nach wie vor Standards eine andere Überlastung und wären konforme! : (

EDIT:

Nur meinen Punkt zu illustrieren, betrachten Sie den folgenden Code:

template <typename T> void foo ( T * );
template <typename T> void foo ( T * const );
template <typename T> void foo ( T [] );
template <typename T> void foo ( T [10] );
template <typename T> void foo ( T [100] );

void bar () 
{
  foo < void() > ( 0 );
}

Hier foo wurde erklärt und neu deklariert mehrmals. Welche Erklärung, und so welcher Parametertyp, sollte der Compiler die Regeln in 14.8.2 aufgeführten anwenden?

Mein Punkt ist, dass der Standard sagt nichts über die oben genannten. Ich würde auch so weit zu sagen, dass jede Formulierung auf diesem würde verlassen müssen sie entweder als „undefiniert“ oder „Implementierung definiert“ Verhalten gehen.

Andere Tipps

Suprisingly genug - das funktioniert in VS2008. Ich glaube nicht, dass das unbedingt Beweis für sie richtiges Verhalten oder nicht, obwohl ...

sein

Visual Studio interpretting

char (&f(T[1]))[1];

als eine Funktion, die ein Array der Größe 1 von T, und gibt eine Referenz auf ein Array von Zeichen der Größe 1.

nimmt

Ich werde versuchen, den Prozess der Vorlage Argument Abzugs zu beschreiben, wie ich es aus der Lektüre die Norm zu verstehen.

  1. Explizite Template-Argumente geprüft werden, wie in 14.8.2 / 2 beschrieben.
  2. Die resultierende Funktion wird als Signatur pro 8.3.5 eingestellt (d.h. Array pointer Zerfall durchgeführt wird).
  3. implizite template Argumente abgeleitet gemäss 14.8.2.1 (dies auf einer teilweise substituierten Signatur von Schritt durchgeführt wird, 2).

Der Abzug für die erste Überlast nicht in Schritt 1, also die Überladungsauflösung die zweite Überlastung zurückkehrt. Ich glaube nicht, dass das Programm schlecht ausgebildet ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top