2015-01-21 15 views
5

Ich möchte eine Funktion Vorlage spezialisieren. Diese Funktion wird in einem Namespace deklariert:Funktion Vorlage Spezialisierung in einem Namespace

namespace foo 
{ 
    template <int> 
    void function(); 
} 

(Der Einfachheit halber wird die Vorlage basiert auf einer int, während in meiner Produktionscode, es ist ein enum class, aber es ist das gleiche Problem Das gleiche gilt für a. Typ basierte Vorlage)

Jetzt mag ich es für einen bestimmten Wert spezialisieren:

template <> 
void foo::function<0>() 
{ 
} 

Dies scheitert mit g++ -std=c++11 (Versionen 4.6, 4.7, 4.8 und 4.9) zu kompilieren:

Spezialisierung von ‚template void foo :: function()‘ in anderen Namespace [-fpermissive]

clang++ -std=c++11 akzeptiert diesen Code.

g ++ akzeptiert auch das folgende Stück:

namespace foo 
{ 
    template <> 
    void function<0>() 
    { 
    } 
} 

Wer ist richtig, gcc oder klappern?

+0

Beide haben Recht. Der einzige Unterschied ist, dass der Klang eine Erweiterung hat, die diese - Nichtstandard - Deklaration ermöglicht. – Ethouris

+0

@Ethouris Dies widerspricht Barrys Antwort. Möchten Sie darauf hinweisen, wo er falsch liegt? – stefan

+0

Nein, tut es nicht, obwohl Sie meine Antwort vielleicht falsch verstanden haben. Ich sagte, dass beide Compiler Recht haben, da beide sagen, dass dieser Code nicht dem Standard C++ entspricht. Der einzige Unterschied ist, dass clang diesen ** noch nicht standardmäßigen ** Code erlaubt, aber behandelt, als würde er eine ** nicht standardisierte Erweiterung ** verwenden. – Ethouris

Antwort

8

Nach der Norm, §14.7.3/2, Hervorhebung von mir:

Eine explizite Spezialisierung wird in einem Namespace deklariert werden, um die spezielle Vorlage einschließen. Eine explizite Spezialisierung deren declarator-ID ist nicht qualifiziert wird im nächsten einschließenden Namespace von die Vorlage deklariert werden, oder, wenn die Namespace-Inline ist (7.3.1), jeder Namespace aus seinem umschließenden Namespace-Set.

Sie müssen template<> function<0>(); in namespace foo setzen. Diese Regel gilt jedoch nur für unqualifizierte declator-id. Wenn Sie eine qualifizierte-ID (wie in foo::function<0>) bereitstellen, glaube ich, dass diese Klausel nicht gelten sollte, die hier richtig kling macht.

Zum Beispiel angesichts der function erklärt die Frage, erwarten würde ich folgendes:

namespace foo { 
    template <> void function<0>(); // valid: unqualified explicit specialization 
            // in the nearest enclosing namespace of the 
            // template 
} 

namespace bar { 
    template <> void function<1>(); // invalid: unqualified explicit specialization 
            // in the wrong namespace 
} 

struct baz { 
    template <> void function<2>(); // invalid: unqualified explicit specialization 
            // not in namespace scope 
}; 

template <> void foo::function<3>(); // valid: qualified explicit specialization 
            // is in a namespace, and id is qualified 

template <> void bar::function<4>(); // invalid: there is no bar::function 
            // to specialize 
+1

globalen Namensraum umschließt die spezielle Vorlage, so wie funktioniert das 'template <> void foo :: function <0>() {}' in globalen Namensraum bricht die Regel, die Sie zitiert? – PowerGamer

+0

@PowerGamer Guter Punkt! Ich wiederhole meine Antwort vollständig. – Barry

+0

@PowerGamer Wie ist der globale Namespace auf jeden Fall "der nächste einschließende Namespace" für den Namespace "foo"? Frage nur - vielleicht hast du recht. Diese Regel verwendet viele ziemlich unklare Aussagen. Es wäre schön, wenn ich den Unterschied zwischen der Definition dieser Sache im "richtigen" und "falschen" Namespace sowie mit "qualifizierter" und "nicht qualifizierter" Deklarator-ID sehen könnte. – Ethouris

Verwandte Themen