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 

Problem mit Template oder operator <<?

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





PostPosted: Mon Nov 03, 2003 6:15 pm    Post subject: Problem mit Template oder operator <<? Reply with quote



Ich versuche eine Klasse zu schreiben, die mir Daten, die ich in einen
Outputstream schicken will, "vorbehandelt" und kommentiert ausgibt. Zu
diesem Zweck hab' ich eine Templateklasse ersonnen. Leider versagt sie
mir den Dienst, es kompiliert nicht, z.B.: bei den Stellen, an denen
eine Ausgabe stattfinden soll. Jetzt wüsste ich gerne zuerst, ob meine
Idee überhaupt funktionieren kann, bevor sich jemand die Mühe macht,
meinen Code zu durchforsten:

Meine Klasse soll als einziges Member einen ofstream enthalten. Neben
dem Konstruktor, in dem ein ofstream übergeben werden kann gibt es drei
Methoden: operator <<, open(char *) und close();

Der operator << soll einfach alle Daten jeden Typs als Referenz
übernehmen und an den selben Operator des output streams
"weiterreichen". Vielleicht hab' ich hier schon ein paar Eigenschaften
der Typprüfung unter C++ übersehen. Dazu soll der operator << als
Templatefunktion implementiert werden

Der Code kommt weiter unten. Erstmal der Fehler.
---8<--------------------*schnipp*
g++ -c -pipe -Wall -W -g -D_REENTRANT -DBUILD_AS_DEF -DBUILD_THREAD
-DQT_THREAD_SUPPORT -DQT_SHARED -DQT_NO_DEBUG
-I/usr/share/qt3/mkspecs/default -I. -I. -I../common_src
-I/usr/include/qt3 -Imocfiles/ -o AS_comm_test.o AS_comm_test.cpp
AS_comm_test.cpp: In member function `void mmain::javareck()':
AS_comm_test.cpp:26: error: no match for 'operator<<' in '
(&defaults::logfile)->my_output_stream::operator<<(const
char*)("Entering mmain::javareck()") << std::endl'
.../common_src/reent_out.h:25: error: candidates are: my_output_stream&
my_output_stream::operator<<(const char*)
---8<--------------------*schnapp*

danach kommen noch haufenweise Kandidaten, die aber sicher die Falschen
sind.

Klassendeklaration:

---8<--------------------*schnipp*

ifndef REENT_OUT_DEF
#define REENT_OUT_DEF

#include #include <list>
#include <iostream>
#include <fstream>
// #include <basic_ostream>

using namespace std;

/* class my_output_stream
* */
class my_output_stream
{
public:
my_output_stream(ofstream&);
template<typename T1>
my_output_stream& operator << (const T1&);
my_output_stream& operator << (const char* const);
void open(char* fn);
void close();

private:
ofstream& os_int;
pthread_mutex_t mut;
bool nl;
};

#endif


---8<-----------------------*schnapp*

Das sourcefile sieht so aus:

---8<-----------------------*schnipp*
#include "reent_out.h"

using namespace std;

my_output_stream::my_output_stream(ofstream& os_new) : os_int(os_new)
{
nl=true;
}

template my_ouput_stream& my_output_stream::operator << (const T1& data)
{
pthread_mutex_lock(&mut);
if (nl)
{
*os_int << getpid() << " ";
}
*os_int << data;
if (typeid(data)==typeid(endl))
{
if (data==endl)
nl=true;
else
nl=false;
}
else
{
nl=false;
}
pthread_mutex_unlock(&mut);
}

my_ouput_stream& my_output_stream::operator << (const char* const data)
{
pthread_mutex_lock(&mut);
if (nl)
{
*os_int << getpid() << " ";
}
*os_int << data;
/* if (typeid(data)==typeid(endl))
{
if (data==endl)
nl=true;
else
nl=false;
}
else
{
nl=false;
} */
pthread_mutex_unlock(&mut);
}

void my_output_stream::open(char* fn)
{
os_int.open(fn);
}

void my_ouput_stream::close()
{
os_int.close();
}

--8<---------------*schnapp*

Die Zeile, die den Fehler schmeisst lautet:

defaults::logfile << "Entering mmain::javareck()" << endl;

und defaults::logfile ist eine statische Instanz von my_output_stream

Tja, dem Fehler zufolge wird der passende Operator nicht gefunden. Was
hab' ich übersehen?

Vielen Dank schon mal,
Moritz

--
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
Torsten Robitzki
Guest





PostPosted: Mon Nov 03, 2003 10:26 pm    Post subject: Re: Problem mit Template oder operator <<? Reply with quote



Moritz Kaiser wrote:
Quote:
defaults::logfile << "Entering mmain::javareck()" << endl;

und defaults::logfile ist eine statische Instanz von my_output_stream

Tja, dem Fehler zufolge wird der passende Operator nicht gefunden. Was
hab' ich übersehen?

Schwer zu sagen, da das was Du uns zeigst nicht ganz zusammen past. In
Deiner Implementierung scheint os_int z.B. ein Zeiger und keine Referenz
zu sein.
std::endl ist eine Funktion. std::basic_ostream hat einen operator<< um
solche Manipulatoren mit sich selbst als Argument aufzurufen. Ein Test,
ob das übergebene Argument vom gleichen Typ wie std::endl() ist, macht
also wenig Sinn, wenn man feststellen möchte, ob einen Zeilenumbruch
geschrieben wurde.

mfg Torsten

--
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
Moritz Kaiser
Guest





PostPosted: Tue Nov 04, 2003 7:50 am    Post subject: Re: Problem mit Template oder operator <<? Reply with quote



Torsten Robitzki wrote:
Quote:
Moritz Kaiser wrote:

defaults::logfile << "Entering mmain::javareck()" << endl;

und defaults::logfile ist eine statische Instanz von my_output_stream

Tja, dem Fehler zufolge wird der passende Operator nicht gefunden. Was
hab' ich übersehen?


Schwer zu sagen, da das was Du uns zeigst nicht ganz zusammen past. In

das hab' ich schon geahnt.

Quote:
Deiner Implementierung scheint os_int z.B. ein Zeiger und keine Referenz
zu sein.

Hab's gesehen, gefixt. Kann aber eigentlich nicht Ursache für den Fehler
sein.

Quote:
std::endl ist eine Funktion. std::basic_ostream hat einen operator<< um
solche Manipulatoren mit sich selbst als Argument aufzurufen. Ein Test,
ob das übergebene Argument vom gleichen Typ wie std::endl() ist, macht
also wenig Sinn, wenn man feststellen möchte, ob einen Zeilenumbruch
geschrieben wurde.

das seh' ich ein. Hab' bis jetzt nirgendwo erfahren, dass die
Manipulatoren Funktionen sind. So gesehen, müsste ich also den Operator
<< nochmal überladen, um endl() "detektieren" zu können. Oder wie müsste
ich bei Funktionen vorgehen?

Andere Frage:
Wie könnte man das anderweitig realisieren? Ich möchte ja vor allem,
dass vor jeder Ausgabezeile die Prozess-ID meines Threads steht, der
gerade was in's Logfile schiebt. Ist es möglich sowas mit Streambuffern
zu erreichen? Ich kann mir unter den Dingern leider noch recht wenig
vorstellen.

Servus,
Moritz

--
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
Werner Salomon
Guest





PostPosted: Tue Nov 04, 2003 9:05 am    Post subject: Re: Problem mit Template oder operator <<? Reply with quote

Moritz Kaiser <ariser (AT) fs (DOT) tum.de> wrote

Quote:
Ich versuche eine Klasse zu schreiben, die mir Daten, die ich in einen
Outputstream schicken will, "vorbehandelt" und kommentiert ausgibt. Zu
diesem Zweck hab' ich eine Templateklasse ersonnen. Leider versagt sie
mir den Dienst, es kompiliert nicht, z.B.: bei den Stellen, an denen
eine Ausgabe stattfinden soll. Jetzt wüsste ich gerne zuerst, ob meine
Idee überhaupt funktionieren kann, bevor sich jemand die Mühe macht,
meinen Code zu durchforsten:
[...]
Der operator << soll einfach alle Daten jeden Typs als Referenz
übernehmen und an den selben Operator des output streams
"weiterreichen". Vielleicht hab' ich hier schon ein paar Eigenschaften
der Typprüfung unter C++ übersehen. Dazu soll der operator << als
Templatefunktion implementiert werden

Der Code kommt weiter unten. Erstmal der Fehler.
---8<--------------------*schnipp*
g++ -c -pipe -Wall -W -g -D_REENTRANT -DBUILD_AS_DEF -DBUILD_THREAD
-DQT_THREAD_SUPPORT -DQT_SHARED -DQT_NO_DEBUG
-I/usr/share/qt3/mkspecs/default -I. -I. -I../common_src
-I/usr/include/qt3 -Imocfiles/ -o AS_comm_test.o AS_comm_test.cpp
AS_comm_test.cpp: In member function `void mmain::javareck()':
AS_comm_test.cpp:26: error: no match for 'operator<<' in '
(&defaults::logfile)->my_output_stream::operator<<(const
char*)("Entering mmain::javareck()") << std::endl'
../common_src/reent_out.h:25: error: candidates are: my_output_stream&
my_output_stream::operator<<(const char*)
---8<--------------------*schnapp*

danach kommen noch haufenweise Kandidaten, die aber sicher die Falschen
sind.

Klassendeklaration:

---8<--------------------*schnipp*
[...]
--8<---------------*schnapp*

Die Zeile, die den Fehler schmeisst lautet:

defaults::logfile << "Entering mmain::javareck()" << endl;

und defaults::logfile ist eine statische Instanz von my_output_stream

Tja, dem Fehler zufolge wird der passende Operator nicht gefunden. Was
hab' ich übersehen?

Hallo Moritz,

ich vermute es liegt an dem 'endl'. lt. Standard ist 'endl' eine
Template-Funktion.
template basic_ostream<charT,traits>& endl( basic_ostream<charT,traits>& os
);

Dafür stellt 'my_output_stream' keinen operator zu Verfügung. Und ich
vermute das steht auch in Deiner Fehlermeldung, in dem Teil, den Du
abgeschnitten hast - hinter "candidates are:" ;-)

Die Behebung des Problems könnte so aussehen, dass Du der Klasse
'my_output_stream' den passenden operator verpasst, der da lauten
würde:
my_output_stream& operator<<
(std::ostream& (* pf)(std::ostream&));

Der Ausdruck '*os_int' dürfte auch nicht übersetzen !?

Weiter ist die Kombination
Quote:
pthread_mutex_lock(&mut);
[Code..]
os_int << data; // <- dieser Ausdruck könnte eine Exception werfen
pthread_mutex_unlock(&mut);

ziemlich gefährlich. Im Falle einer Exception wird kein unlock-Mutex
aufgerufen. Besser ist eine RAII-Konstruktion (siehe
<http://www.boost.org/libs/thread/doc/lock_concept.html>)

Zum Schluß noch eine Bemerkung zu der Klasse 'my_output_stream'. Bei
so einen selbstgebastelten Stream ist alles mögliche zu beachten (z.B.
endl, Fehlerverhalten, usw.). Ich habe Deine Anwendung nicht so ganz
verstanden, aber vielleicht solltest Du mal über eine Lösung via
Manipulator nachdenken.
Die Anwendung könnte dann etwa so aussehen:

std::ostream out( .. ); // oder 'cout', oder fstream, oder ...
out << "Ausgabe: " << my_format( .. Text, oder andere Typen ) << endl;

// mit:
template< typename T >
class My_Formater { ..
friend std::ostream& operator<<( std::ostream& out, const
My_Formater& f )
{
// hier geschieht die Ausgaben via f.m_x
return out;
}
private:
T m_x; // ausszugebender Typ
};

template< typename T >
My_Formater< T > my_format( const T& x )
{ return My_Formater< T >( x ); }

Gruß
Werner

--
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
Torsten Robitzki
Guest





PostPosted: Tue Nov 04, 2003 6:30 pm    Post subject: Re: Problem mit Template oder operator <<? Reply with quote

Moritz Kaiser wrote:
Quote:
Torsten Robitzki wrote:
std::endl ist eine Funktion. std::basic_ostream hat einen operator
um solche Manipulatoren mit sich selbst als Argument aufzurufen. Ein
Test,
ob das übergebene Argument vom gleichen Typ wie std::endl() ist, macht
also wenig Sinn, wenn man feststellen möchte, ob einen Zeilenumbruch
geschrieben wurde.


das seh' ich ein. Hab' bis jetzt nirgendwo erfahren, dass die
Manipulatoren Funktionen sind. So gesehen, müsste ich also den Operator
nochmal überladen, um endl() "detektieren" zu können. Oder wie müsste
ich bei Funktionen vorgehen?

Im Prinzip mit
my_output_stream& operator<<(std::ostream&(*func)(std::ostream&))
und einem Vergleich von func mit der Adresse von endl char_traits. Habe ich aber leider nicht hinbekommen. Vielleicht
hat jemand eine Idee.

Quote:
Andere Frage:
Wie könnte man das anderweitig realisieren? Ich möchte ja vor allem,
dass vor jeder Ausgabezeile die Prozess-ID meines Threads steht, der
gerade was in's Logfile schiebt. Ist es möglich sowas mit Streambuffern
zu erreichen? Ich kann mir unter den Dingern leider noch recht wenig
vorstellen.

Prozess-ID Deines Threads? Sollte eigentlich gleich sein für alle
threads in einem Prozess. Streambuffer ist eine gute Idee. Vielleicht
findest Du hier ein wenig Anregung (ist noch nicht fertig).
http://www.robitzki.de/trace.cc; http://www.robitzki.de/trace.h

Bei dem Erkennen von endl, stellt sich die Frage, ob Du wirklich eine
Kombination von 'n' und dem flushen des streambuffers erkennen möchtest
oder nur das 'n'. Das explizite flushen des streams sollte man daran
erkennen können, das sync() nicht von overflow() aufgerufen wurde. Da
alle Zeichen durch den Streambuffer wandern, kann man auch noch das 'n'
erkennen.

mfg Torsten

--
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.