Errore su msvc ++ con estensione iostream
-
29-10-2019 - |
Domanda
Sto scrivendo una classe di Output Manager per la mia applicazione e sebbene la mia classe funzioni su G ++ sotto Linux, non si compilerà in MSVC ++ 2010.
Ecco una versione SSCCE del mio programma:
#include <iostream>
#include <malloc.h>
#include <sstream>
#include <fstream>
template<class cT, class traits=std::char_traits<cT> >
class BasicE3OutStream: public std::basic_ostream<cT, traits> {
public:
BasicE3OutStream() :
std::basic_ios<cT, traits>(), std::basic_ostream<cT, traits>(0), mBuffer() {
resetModifiers();
mLineBuffer=(std::stringstream*) malloc(sizeof(std::stringstream));
mLineBuffer=new (mLineBuffer) std::stringstream();
}
BasicE3OutStream(const BasicE3OutStream<cT,traits> &) {
}
virtual ~BasicE3OutStream() {
delete mLineBuffer;
mLineBuffer=NULL;
}
void resetModifiers() {
mDebug=false;
mMemory=false;
}
void open(const char* fileName) {
mBuffer.open(fileName, std::stringstream::out);
}
void close() {
mBuffer.close();
}
template<class T>
BasicE3OutStream& operator<<(T val) {
(*mLineBuffer)<<val;
return (*this);
}
BasicE3OutStream& operator<<(char* val) {
(*mLineBuffer)<<val;
return (*this);
}
BasicE3OutStream& operator<<(std::string val) {
(*mLineBuffer)<<val;
return (*this);
}
void addLineFeed() {
std::string modifier;
modifier="";
if (mDebug)
modifier+="[DEBUG] ";
else if (mMemory)
modifier+="[MEMORY] ";
mBuffer<<modifier<<mLineBuffer->str()<<"\n";
mLineBuffer->~basic_stringstream();
mLineBuffer=new (mLineBuffer) std::stringstream();
resetModifiers();
}
void flush() {
mBuffer.flush();
resetModifiers();
}
void setFlag(int f) {
if (f==0)
mDebug=true;
else if (f==1)
mMemory=true;
}
public:
std::basic_ofstream<cT, traits> mBuffer;
std::stringstream* mLineBuffer;
bool mDebug, mMemory;
};
template<class cT, class traits, class T>
BasicE3OutStream<cT, traits>& operator<<(BasicE3OutStream<char, traits>& str , T val) {
str.operator <<(val);
return (str);
}
typedef BasicE3OutStream<char> E3OutStream;
template<class charT, class traits>
BasicE3OutStream<charT, traits>& endl(BasicE3OutStream<charT, traits>& os) {
os.addLineFeed();
return (os);
}
template<class charT, class traits>
BasicE3OutStream<charT, traits>& flush(BasicE3OutStream<charT, traits>& os) {
os.flush();
return (os);
}
template<class charT, class traits>
BasicE3OutStream<charT, traits>& debug(BasicE3OutStream<charT, traits>& os) {
os.setFlag(0);
return (os);
}
template<class charT, class traits>
BasicE3OutStream<charT, traits>& memory(BasicE3OutStream<charT, traits>& os) {
os.setFlag(1);
return (os);
}
/**
* Io manipulator, allows to use endl and other modificators
*/
template<class charT, class traits> BasicE3OutStream<charT, traits>& operator<<(
BasicE3OutStream<charT, traits> &s
, BasicE3OutStream<charT, traits>& (*iomanip)(BasicE3OutStream<charT, traits>&)) {
return (iomanip(s));
}
int main() {
E3OutStream s;
s.open("output.txt");
s<<debug<<"Debug info"<<endl;
s<<flush;
s<<memory<<"Memory info"<<endl;
s<<flush;
s.close();
}
Funziona bene in G ++, tuttavia su MSVC ricevo un errore del compilatore:
1>------ Build started: Project: sscce, Configuration: Debug Win32 ------
1> main.cpp
1>c:\users\guillaume\documents\visual studio 2010\projects\sscce\sscce\main.cpp(129): error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion)
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(679): could be 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(726): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(764): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(811): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(937): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const signed char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(944): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,signed char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(951): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const unsigned char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(958): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,unsigned char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(1085): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const std::error_code &)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\users\guillaume\documents\visual studio 2010\projects\sscce\sscce\main.cpp(43): or 'BasicE3OutStream<cT> &BasicE3OutStream<cT>::operator <<(char *)'
1> with
1> [
1> cT=char
1> ]
1> c:\users\guillaume\documents\visual studio 2010\projects\sscce\sscce\main.cpp(48): or 'BasicE3OutStream<cT> &BasicE3OutStream<cT>::operator <<(std::string)'
1> with
1> [
1> cT=char
1> ]
1> while trying to match the argument list '(E3OutStream, overloaded-function)'
1>c:\users\guillaume\documents\visual studio 2010\projects\sscce\sscce\main.cpp(130): error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion)
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(679): could be 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(726): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(764): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(811): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(937): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const signed char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(944): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,signed char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(951): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const unsigned char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(958): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,unsigned char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(1085): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const std::error_code &)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\users\guillaume\documents\visual studio 2010\projects\sscce\sscce\main.cpp(43): or 'BasicE3OutStream<cT> &BasicE3OutStream<cT>::operator <<(char *)'
1> with
1> [
1> cT=char
1> ]
1> c:\users\guillaume\documents\visual studio 2010\projects\sscce\sscce\main.cpp(48): or 'BasicE3OutStream<cT> &BasicE3OutStream<cT>::operator <<(std::string)'
1> with
1> [
1> cT=char
1> ]
1> while trying to match the argument list '(E3OutStream, overloaded-function)'
1>c:\users\guillaume\documents\visual studio 2010\projects\sscce\sscce\main.cpp(131): error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion)
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(679): could be 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(726): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(764): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(811): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(937): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const signed char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(944): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,signed char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(951): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const unsigned char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(958): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,unsigned char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(1085): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const std::error_code &)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\users\guillaume\documents\visual studio 2010\projects\sscce\sscce\main.cpp(43): or 'BasicE3OutStream<cT> &BasicE3OutStream<cT>::operator <<(char *)'
1> with
1> [
1> cT=char
1> ]
1> c:\users\guillaume\documents\visual studio 2010\projects\sscce\sscce\main.cpp(48): or 'BasicE3OutStream<cT> &BasicE3OutStream<cT>::operator <<(std::string)'
1> with
1> [
1> cT=char
1> ]
1> while trying to match the argument list '(E3OutStream, overloaded-function)'
1>c:\users\guillaume\documents\visual studio 2010\projects\sscce\sscce\main.cpp(132): error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion)
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(679): could be 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(726): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(764): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(811): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(937): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const signed char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(944): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,signed char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(951): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const unsigned char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(958): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,unsigned char)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(1085): or 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const std::error_code &)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\users\guillaume\documents\visual studio 2010\projects\sscce\sscce\main.cpp(43): or 'BasicE3OutStream<cT> &BasicE3OutStream<cT>::operator <<(char *)'
1> with
1> [
1> cT=char
1> ]
1> c:\users\guillaume\documents\visual studio 2010\projects\sscce\sscce\main.cpp(48): or 'BasicE3OutStream<cT> &BasicE3OutStream<cT>::operator <<(std::string)'
1> with
1> [
1> cT=char
1> ]
1> while trying to match the argument list '(E3OutStream, overloaded-function)'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Qualsiasi aiuto sarebbe molto apprezzato, Guillaume
MODIFICARE
Grazie a questo consigli, sono stato in grado di capire che in quel caso non è stato utile estendere iostream poiché avevo già una variabile di Stream come membro. Dato che non so abbastanza il funzionamento interno della libreria STD, ho reso la mia classe indipendente e ha funzionato su MSVC e G ++:
#include <iostream>
#include <malloc.h>
#include <sstream>
#include <fstream>
class BasicE3OutStream {
public:
BasicE3OutStream() :
mBuffer() {
resetModifiers();
mLineBuffer=(std::stringstream*) malloc(sizeof(std::stringstream));
mLineBuffer=new (mLineBuffer) std::stringstream();
}
BasicE3OutStream(const BasicE3OutStream &) {
}
virtual ~BasicE3OutStream() {
delete mLineBuffer;
mLineBuffer=NULL;
}
void resetModifiers() {
mDebug=false;
mMemory=false;
}
void open(const char* fileName) {
mBuffer.open(fileName, std::stringstream::out);
}
void close() {
mBuffer.close();
}
template<class T>
BasicE3OutStream& operator<<(T val) {
(*mLineBuffer)<<val;
return (*this);
}
void addLineFeed() {
std::string modifier;
modifier="";
if (mDebug)
modifier+="[DEBUG] ";
else if (mMemory)
modifier+="[MEMORY] ";
mBuffer<<modifier<<mLineBuffer->str()<<"\n";
mLineBuffer->str("");
resetModifiers();
}
void flush() {
mBuffer.flush();
resetModifiers();
}
void setFlag(int f) {
if (f==0)
mDebug=true;
else if (f==1)
mMemory=true;
}
public:
std::ofstream mBuffer;
std::stringstream* mLineBuffer;
bool mDebug, mMemory;
};
BasicE3OutStream& endl(BasicE3OutStream& os) {
os.addLineFeed();
return (os);
}
BasicE3OutStream& flush(BasicE3OutStream& os) {
os.flush();
return (os);
}
BasicE3OutStream& debug(BasicE3OutStream& os) {
os.setFlag(0);
return (os);
}
BasicE3OutStream& memory(BasicE3OutStream& os) {
os.setFlag(1);
return (os);
}
/**
* Io manipulator, allows to use endl and other modificators
*/
BasicE3OutStream& operator<<(
BasicE3OutStream &s
, BasicE3OutStream& (*iomanip)(BasicE3OutStream&)) {
return (iomanip(s));
}
typedef BasicE3OutStream E3OutStream;
int main() {
E3OutStream s;
s.open("output.txt");
s<<debug<<"Debug info"<<endl;
s<<flush;
s<<memory<<"Memory info"<<endl;
s<<flush;
s.close();
}
Soluzione
Il nucleo del problema è che stai inviando puntatori di funzioni al tuo flusso, che GCC sembra sapere come gestire, ma Msvc ++ no. Ad ogni modo, dubito che tu volesse salvare l'indirizzo del debug
/endl
/flush
/memory
funzioni.
La risoluzione del passo successivo è farne quelle oggetti invece di funzioni che visualizzi.
Tuttavia, c'è un quantità Sbagliato con questo codice. Vale a dire, esistono già endl
e flush
Oggetti, che dovresti usare. Inoltre, ciascuno BasicE3OutStream
ha tre flussi sottostanti, uno ereditato da, su cui funzionano tutte le funzioni (incluso endl
e tale, che presumo sia il motivo per cui li hai sostituiti) e mBuffer
e mLineBuffer
, (nessuno dei membri è necessario per quello che stai facendo). (Un'altra nota a margine, reimpostare uno stringstream con mLineBuffer.str("");
, non posizionamento nuovo)
Il modo semplice per fare quello che vuoi è sovraccaricare ciascuno dei operator<<
membri di a basic_ostream
, e ovunque ci sia una nuova linea, inserisci [DEBUG]
o [MEMORY]
Come appropriato, non è necessario tamponare. (L'ho fatto, non è pazzesco difficile)
C'è probabilmente un Giusto modo per farlo usando un flusso con diversi tratti char o sovraccaricando determinate funzioni virtuali o sostituendo il buffer, ma i flussi sono complicati e non lo so Giusto modo.