C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Templates, Triends und Spezialisierung

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German)
View previous topic :: View next topic  
Author Message
Johannes Mueller
Guest





PostPosted: Mon Oct 24, 2005 9:13 am    Post subject: Templates, Triends und Spezialisierung Reply with quote



Hallo...

Ich habe folgendes Problem. Ich habe eine template-Klasse und eine
Spezialisierung der template-Klasse. Die spezialisierte Klasse hat
einen Objekt der generischen template-Klasse. Jetzt muss diese
Spezialisierung auf den private-Bereich der generischen Klasse
zugreifen können. Das wollte ich mit einem friend lösen. Das klappt je
nach Kompilerversion nicht. Versucht habe ich g++-3.3 und g++-3.4

Beispielcode:

//////////////////////////////////////////////////////////////////////////////
#include <iostream>

using namespace std;

template<class T> class TemplateClass
{
public:

// Je nach Kompilerversion...
friend void TemplateClass<int>::friend_function();
// friend class TemplateClass<int>;

TemplateClass()
{
cout << "This is TemplateClass.n";
}

private:
void private_function()
{
cout << "This is TemplateClass::private_function()n";
}

void friend_function()
{
}

};

template<> class TemplateClass<int>
{
public:
TemplateClass<int>( TemplateClass<double>& foo )
: foo_( foo )
{
cout << "This is TemplateClass friend_function();
}

private:
void friend_function()
{
cout << "This is TemplateClass foo_.private_function();
}

TemplateClass<double>& foo_;
};


int main()
{
TemplateClass<double> foo;
TemplateClass<int> bar( foo );
}
//////////////////////////////////////////////////////////////////////////////


joh@ww1-321lxjm $ g++-3.3 -o friendtest friendtest.cc
joh@ww1-321lxjm $ g++-3.4 -o friendtest friendtest.cc
friendtest.cc: In instantiation of `TemplateClass<double>':
friendtest.cc:41: instantiated from here
friendtest.cc:39: Fehler: »void TemplateClass<int>::friend_function()« ist privat
friendtest.cc:6: Fehler: in diesem Zusammenhang
joh@ww1-321lxjm $

Wenn ich jetzt die Kommentare bei den beiden friend-Zeilen vertausche,
ist es umgekehrt. g++-3.4 kompiliert nicht, g++-3.3 nicht.

Was sagen da andere Kompiler dazu? Wie sollte man es schreiben?

Danke

joh

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
Back to top
Johannes Mueller
Guest





PostPosted: Mon Oct 24, 2005 8:23 pm    Post subject: Re: Templates, Triends und Spezialisierung Reply with quote



Johannes Mueller <joh_im_usenet (AT) gmx (DOT) de> skribis:
Quote:
Ich habe folgendes Problem. Ich habe eine template-Klasse und eine
Spezialisierung der template-Klasse. Die spezialisierte Klasse hat
einen Objekt der generischen template-Klasse. Jetzt muss diese
Spezialisierung auf den private-Bereich der generischen Klasse
zugreifen können. Das wollte ich mit einem friend lösen. Das klappt je
nach Kompilerversion nicht. Versucht habe ich g++-3.3 und g++-3.4

Beispielcode:

[...]

Also, das sieht mir nach einem Compilerbug aus. Sobald ich in der
generischen TemplateClass eine Funktion aus der spezialisierten
TemplateClass<int> zum Freund deklariere, kann ich von
TemplateClass<double> keine öffentliche Funktion von
TemplateClass<int> mehr aufrufen.

/////////////////////////////////////////////////////////////////////////////
#include <iostream>

using namespace std;

template<class T> class TemplateClass
{
public:
// Wenn man folgende Zeile mit reinholt, meckert g++-3.4. Bug?
// friend void TemplateClass<int>::friend_function();

TemplateClass() {}

void public_function()
{
cout << "This is TemplateClass::public_function()n";
}

private:
void friend_function() {}

};

template<> class TemplateClass<int>
{
public:
TemplateClass<int>( TemplateClass<double>& foo )
: foo_( foo )
{
foo_.public_function();
}

private:
void friend_function() {}
TemplateClass<double>& foo_;
};


int main()
{
TemplateClass<double> foo;
TemplateClass<int> bar( foo );
}
/////////////////////////////////////////////////////////////////////////////

joh@ww1-321lxjm $ g++-3.4 -o friendtest friendtest.cc
friendtest.cc: In instantiation of `TemplateClass<double>':
friendtest.cc:31: instantiated from here
friendtest.cc:35: Fehler: »void TemplateClass<int>::friend_function()« ist privat
friendtest.cc:9: Fehler: in diesem Zusammenhang
joh@ww1-321lxjm $

Ist das ein Compilerbug oder stehe ich da auf dem Schlauch?

joh

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Thomas Mang
Guest





PostPosted: Tue Oct 25, 2005 6:52 pm    Post subject: Re: Templates, Triends und Spezialisierung Reply with quote




"Johannes Mueller" <joh_im_usenet (AT) gmx (DOT) de> schrieb im Newsbeitrag
news:3s4u54Fmcu2hU1 (AT) news (DOT) dfncis.de...
Quote:
Johannes Mueller <joh_im_usenet (AT) gmx (DOT) de> skribis:

Also, das sieht mir nach einem Compilerbug aus. Sobald ich in der
generischen TemplateClass eine Funktion aus der spezialisierten
TemplateClass<int> zum Freund deklariere, kann ich von
TemplateClass<double> keine öffentliche Funktion von
TemplateClass<int> mehr aufrufen.


////////////////////////////////////////////////////////////////////////////

/
Quote:
#include <iostream

using namespace std;

template {
public:
// Wenn man folgende Zeile mit reinholt, meckert g++-3.4. Bug?
// friend void TemplateClass<int>::friend_function();

TemplateClass() {}

void public_function()
{
cout << "This is TemplateClass::public_function()n";
}

private:
void friend_function() {}

};
Ist das ein Compilerbug oder stehe ich da auf dem Schlauch?


Nein, es ist kein Compilerbug.
Du willst eine Funktion einer Klasse zum friend erklären. Dafür muss aber
die gesamte Klassendefinition der Klasse, die die Funktion enthält die Du
zum friend machen willst, zur Verfügung stehen. Das wäre hier
TemplateClass ist dasselb wie:

class A
{
friend void B::bar();
};

class B
{
public:
void bar(){}
};


Das geht auch nicht.
Entweder wird das ganze TemplateClass<int> zum friend erklärt, dann nimmt
man die Syntax, die Du im ersten post erwähnt hast, die aber einer Deiner
Compiler nicht frisst:

friend class TemplateClass<int>;


Die andere Variante ist komplizierter.
Die Spezialisierung TemplateClass<int> muß vor der generischen Version
stehen. Damit ich aber überhaupt spezialisieren kann, braucht man eine
Deklaration des generischen templates. Weiters muss die Funktion, die zum
friend ernannt wird, innerhalb der Klasse, die die friend-Deklaration
beinhaltet, zugreifbar ("accessible") sein, also public, oder muss
ihrerseits eine friend-Deklaration beinhalten. De facto erklärt man eine
Klasse zum friend, nur damit die dann eine friend-Deklaration durchführen
kann !

Codebeispiel, kommentiert:

#include <iostream>
using namespace std;

// Deklaration eines class template
template <typename T> class TemplateClass;

// Die Spezialisierung
// Ist technisch gesehen eine eigenständige Klasse, ohne jeden Bezug zu
TemplateClass<T>
template<> class TemplateClass<int>
{
public:
TemplateClass<int>( TemplateClass<double>& foo );

private:

void friend_function() {}
TemplateClass<double>& foo_;

// Notwendig !!!
// Etwas schräg: hier ist void friend_function() private. Damit eine andere
Klasse diese Funktion zum friend deklarieren kann, braucht diese andere
Klasse aber Zugriff auf void TemplateClass<int>::friend_function(). Deshalb
werden alle TemplateClass<T> zum friend erklärt.
template <typename> friend class TemplateClass;
};

// generische Version
template<class T> class TemplateClass
{
public:

// klappt
// TemplateClass<int> ist definiert, und die Klasse hat Zugriff auf
TemplateClass<int>::friend_function().
friend void TemplateClass<int>::friend_function();

TemplateClass() {}

void public_function()
{
cout << "This is TemplateClass::public_function()n";
}

private:
void friend_function() {}

};

// Definition erst hier, nachdem sich mal jeder mit jedem angefreundet hat.
TemplateClass : foo_( foo )
{
foo_.public_function();
}

int main()
{
TemplateClass<double> foo;
TemplateClass<int> bar( foo );
}



Ich mag die Regeln auch nicht wer wen wann zum friend erklären darf. Die
sind unnötig kompliziert. Mir wäre lieber, eine friend-Deklaration selber
braucht keinen Zugriff auf den der zum friend erklärt wird, und Definitionen
müssen auch nicht da sein - wenn es diese Funktion / nested name nicht
gibt, wird sie einfach ignoriert. Aber Standard sagt es ist nun mal so,
basta.


Thomas

--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.