 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Moritz Kaiser Guest
|
Posted: Mon Nov 03, 2003 6:15 pm Post subject: Problem mit Template oder operator <<? |
|
|
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
|
Posted: Mon Nov 03, 2003 10:26 pm Post subject: Re: Problem mit Template oder operator <<? |
|
|
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
|
Posted: Tue Nov 04, 2003 7:50 am Post subject: Re: Problem mit Template oder operator <<? |
|
|
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
|
Posted: Tue Nov 04, 2003 9:05 am Post subject: Re: Problem mit Template oder operator <<? |
|
|
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
|
Posted: Tue Nov 04, 2003 6:30 pm Post subject: Re: Problem mit Template oder operator <<? |
|
|
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 |
|
 |
|
|
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
|
|