2016-06-03 12 views
5

Welcher der Compiler ist richtig?Kann ein privates statisches Element als Standardargument für eine Elementfunktion seiner Klasse verwendet werden?

class A 
{ 
public: 
    template <typename T> 
    void fun(void (*f)() = funPrivate<T>) {} 
private: 
    template <typename T> 
    static void funPrivate() {} 
}; 

int main(int argc, char** argv) 
{ 
    A a; 
    a.fun<int>(); 
    return 0; 
} 

Compiliert fein auf: gcc Version 4.8.5 (Ubuntu 4.8.5-2ubuntu1 ~ 14.04.1)

Ergebnisse in einem Fehler auf: Klirren Version 3.4-1ubuntu3 (Tags/RELEASE_34/final) (basierend auf LLVM 3,4)

a.cpp:5:27: error: 'funPrivate' is a private member of 'A' 
    void fun(void (*f)() = funPrivate<T>) {} 
          ^~~~~~~~~~~~~ 
    a.cpp:14:3: note: in instantiation of default function argument expression for 'fun<int>' required here 
     a.fun<int>(); 
    ^
    a.cpp:8:16: note: declared private here 
     static void funPrivate() {} 
      ^
1 error generated. 
+2

Dies könnte mit der Optimierung zusammenhängen. Die fragliche Zeile tut nichts, also könnte GCC es optimieren. GCC klage nicht immer über Fehler in Sachen, die es optimiert. Ich wäre gespannt, was passiert ist, wenn Sie tatsächlich versucht haben, diesen Funktionszeiger zu verwenden. –

+0

@WilliamKappler [Nichts geändert.] (Http://coliru.stacked-crooked.com/a/96df544565dac680) – songyuanyao

+0

Seltsamerweise scheint clang es zu akzeptieren, wenn Sie 'funPrivate' nicht eine Vorlage machen. –

Antwort

2

§ 11

8 Die Namen in einem Standardargument (8.3.6) werden zum Zeitpunkt der Deklaration gebunden, und der Zugriff wird an diesem Punkt und nicht an irgendwelchen Punkten der Verwendung des Standardarguments überprüft. Die Zugriffsüberprüfung auf Standardargumente in Funktionsvorlagen und in Mitgliedsfunktionen von Klassenvorlagen erfolgt wie in 14.7.1 beschrieben.

§ 14.7.1

12 Wenn eine Funktionsvorlage f in eine Art und Weise aufgerufen wird, die ein Standard-Argument erfordert verwendet werden, die abhängigen Namen nachgeschlagen werden die Semantik Einschränkungen überprüft, Die Instanziierung einer beliebigen Vorlage, die im Standardargument verwendet wird, erfolgt so, als ob das Standardargument ein Initialisierer in einer Funktionsschablonenspezialisierung mit demselben Bereich, denselben Schablonenparametern und demselben Zugriff wie der Funktionsschablone f gewesen wäre verwendet bei diesem p Salbe. Diese Analyse wird Standardargument Instanziierung genannt. Das instanziierte Standardargument wird dann als Argument von f verwendet.

Also, nach diesem würde ich vermuten, dass die Interpretation von GCC richtig ist. fun hat Zugriff auf private Mitglieder, daher sollten die Standardargumente in diesem Zugriff berücksichtigt werden. Aber ich lese zwischen den Zeilen, die 14.7.1 (12) für Mitgliedervorlagen und nicht nur für Funktionsvorlagen gilt. Ich mag auch falsch verstehen, dass 14.7.1 (12) bedeutet.

+0

Wenn 14.7.1 (12) durch Template-Funktionen impliziert auch Template-Methode, dies wäre eine definitive Antwort – user1650441

0

Ich habe Code in msvc13 getestet. Dieser Code funktioniert:

class A 
{ 
    template <typename T> 
    static void funPrivate() {} 
public: 
    template <typename T> 
    void fun(void (*f)() = funPrivate<T>) {} 
};