Bitte werfen Sie einen Blick auf dieses Code-Snippet. Ich weiß, dass es nicht viel Sinn macht, ist es nur das Problem veranschaulichen soll ich begegnet bin:Die Memberschablonenfunktion der Klasse A, die in Klasse B als Freund deklariert wurde, kann nicht auf private Member der Klasse A zugreifen (nur Clang).
#include <iostream>
using namespace std;
struct tBar
{
template <typename T>
void PrintDataAndAddress(const T& thing)
{
cout << thing.mData;
PrintAddress<T>(thing);
}
private:
// friend struct tFoo; // fixes the compilation error
template <typename T>
void PrintAddress(const T& thing)
{
cout << " - " << &thing << endl;
}
};
struct tFoo
{
friend void tBar::PrintDataAndAddress<tFoo>(const tFoo&);
private:
int mData = 42;
};
struct tWidget
{
int mData = 666;
};
int main()
{
tBar bar;
bar.PrintDataAndAddress(tWidget()); // Fine
bar.PrintDataAndAddress(tFoo()); // Compilation error
return 0;
}
Der obige Code löst den folgenden Fehler:
source_file.cpp:10:3: error: 'PrintAddress' is a private member of 'tBar' PrintAddress(thing); source_file.cpp:42:6: note: in instantiation of function template >specialization 'tBar::PrintDataAndAddress' requested here bar.PrintDataAndAddress(tFoo()); // Compilation error source_file.cpp:17:7: note: declared private here void PrintAddress(const T& thing)
aber nur in Clang ++. GCC und MSVC sind in Ordnung mit ihm (man schnell, dass in http://rextester.com/l/cpp_online_compiler_clang durch Einfügen diesen Code testen)
Es scheint, als ob tBar::PrintDataAndAddress<tFoo>(const tFoo&)
wird den gleichen Zugang wie tFoo
verwenden, wo es befreundete wird. Ich weiß das, weil tFoo
in tBar
befreundet dieses Problem behebt. Das Problem verschwindet auch, wenn tBar::PrintDataAndAddress
eine Nicht-Template-Funktion ist.
Ich konnte im Standard nichts finden, das dieses Verhalten erklärt. Ich glaube, es könnte eine schlechte Interpretation von 14.6.5 - temp.inject sein, aber ich kann nicht behaupten, dass ich alles davon gelesen habe.
Weiß jemand, ob Clang richtig ist, den obigen Code nicht zu kompilieren? Können Sie bitte den entsprechenden C++ - Standardtext zitieren, wenn dies der Fall ist?
Es scheint, dass für dieses Problem das private Element, auf das zugegriffen wird, eine Vorlagenfunktion sein muss. Beispiel: Wenn wir im obigen Beispiel PrintAddress zu einer Nicht-Template-Funktion machen, wird der Code ohne Fehler kompiliert.
Vielleicht vermisse ich etwas, aber es scheint mir völlig vernünftig, dass clang das nicht kompiliert. Was ich merkwürdig finde, ist, dass die Friend-Deklaration auskommentiert, veranlasst dies zu kompilieren. Es scheint mir, als ob es sich nicht kompilieren sollte. Ich habe in der Vergangenheit schon einige Fälle gesehen, in denen gcc "zu lässige" Bugs in Bezug auf Freundschaft hat, wo eine Menge Templating involviert ist. Ich denke, das ist hier der Fall. –
@NirFriedman warum denkst du es ist vernünftig, dass Clang das nicht kompiliert? Es scheint mir kontraintuitiv zu sein. Klasse A gibt einem Freund Zugriff auf eine Memberfunktion der Klasse B (in diesem Fall eine Template-Funktion), damit er Zugriff auf die privaten und geschützten Members von A erhält, aber warum sollte der Zugriff auf die privaten/geschützten Member von B entfernt werden? – TheProgammerd
Sieht für mich wie ein Clang Bug aus. Suche nach, ob es bereits gemeldet wurde. – aschepler