473,614 Members | 2,342 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Deriving my own stream class

I want to write my own class derived from the ostream class.

I have been getting errors with my templates:

First, I get an error writing a nested template. If I leave the function
definition inside template class definition (commented out at //1) then
it compiles and runs fine, but if I declare and define the function
separately (at //2).

Is the following syntax supported by g++?
template<typena me charT, typename Traits>
template<typena me T>
as I get the compiler error
"mystream.cpp:4 7: error: too many template-parameter-lists"

I can't get the use_facet command to work (commented out at //3) as I no
longer have visibility of ostr for getloc and can't call it on my
derived class. Is there another way of achieving this?

I can't get the manipulator function / object combination to compile.
"mystream_test. cpp:11: error: no matching function for call to
‘setfmt(const char [6])’"
Do I need to explicitly qualify the template?

Finally, the compiler seems to get confused by the output operator in
the manipulator (at //4) and issues the following warning:
"mystream.h :41: warning: friend declaration ‘Ostream&
operator<<(Ostr eam&, const osmanip<Ostream , Arg>&)’ declares a
non-template function
mystream.h:41: warning: (if this is not what you intended, make sure the
function template has already been declared and add <after the
function name here) -Wno-non-template-friend disables this warning"

Are these problems due to my own misunderstandin g of templates?

thanks

dan

I have written my templates in three file (mystream.h, mystream.cpp and
mystream_test.c pp) and compiling with g++ 4.2.3

// mystream.h
#include <iostream>
#ifndef __MY_STREAM_H
#define __MY_STREAM_H

template <typename charT, typename Traits=std::cha r_traits<charT
class CMyStream : virtual public std::basic_ostr eam<charT, Traits>
{
public:
charT *m_fmt;

public:
// constructor
CMyStream(std:: basic_ostream<c harT, Traits>& ostr, const char *fmt);
// destructor
~CMyStream();
// change format string
std::basic_ostr eam<charT, Traits>& format(const char *fmt);
// retrieve format string
charT *format() const;

// output operator
template<typena me T>
friend CMyStream& operator<<(CMyS tream& ostr, T val); //1
// {
// (std::basic_ost ream<charT, Traits>&)ostr << ostr.m_fmt << " ";
// (std::basic_ost ream<charT, Traits>&)ostr << val;
// }

};

template <class Ostream, class Arg>
class osmanip {
public:
osmanip(Ostream & (*pf)(Ostream&, Arg), Arg arg);

protected:
Ostream& (*pf_)(Ostream& , Arg);
Arg arg_;

friend Ostream&
operator<< (Ostream& ostr, const osmanip<Ostream ,Arg>& manip);
};

template <class Ostream, class Arg>
Ostream&
operator<< (Ostream& ostr, const osmanip<Ostream , Arg>& manip);

template <class charT, class Traits>
inline std::basic_ostr eam<charT,Trait s>&
sfmt(std::basic _ostream<charT, Traits>& ostr, const char* f);

template <class charT, class Traits>
inline osmanip<std::ba sic_ostream<cha rT, Traits>, const char*>
setfmt(const char* fmt);

#include "mystream.c pp"

#endif /* __MY_STREAM_H */

// mystream.cpp
#include "mystream.h "

#ifndef __MY_STREAM_CPP
#define __MY_STREAM_CPP

using std::basic_ostr eam;
using std::use_facet;
using std::ctype;

template <typename charT, typename Traits>
CMyStream<charT , Traits>::CMyStr eam(basic_ostre am<charT, Traits>& ostr,
const char *fmt = "log")
: std::ostream(os tr.rdbuf())
{
m_fmt = new charT[strlen(fmt)];
use_facet<ctype <charT(ostr.get loc()).widen(fm t, fmt+strlen(fmt) ,
m_fmt);
}

template <typename charT, typename Traits>
CMyStream<charT , Traits>::~CMySt ream()
{
delete[] m_fmt;
}

template <typename charT, typename Traits>
basic_ostream<c harT, Traits>&
CMyStream<charT , Traits>::format (const char *fmt)
{
delete[] m_fmt;
m_fmt = new charT[strlen(fmt)];
// use_facet<ctype <charT(ostr.get loc()).widen(fm t, fmt+strlen(fmt) ,
m_fmt); //3
return *this;
}

template <typename charT, typename Traits>
charT *
CMyStream<charT , Traits>::format () const
{
charT *p = new charT[Traits::length( m_fmt)];
Traits::copy(p, m_fmt, Traits::length( m_fmt));
return p;
}

template <typename charT, typename Traits=std::cha r_traits<charT
template<typena me T>
CMyStream<charT , Traits>& operator<<(CMyS tream<charT, Traits>& ostr, //2
T val)
{
(basic_ostream< charT, Traits>&)ostr << ostr.m_fmt << " ";
(basic_ostream< charT, Traits>&)ostr << val;
}

template <class Ostream, class Arg>
osmanip<Ostream , Arg>::osmanip(O stream& (*pf)(Ostream&, Arg), Arg arg)
: pf_(pf) , arg_(arg)
{
;
}

//4
template <class Ostream, class Arg>
Ostream& operator<< (Ostream& ostr, const osmanip<Ostream , Arg>& manip)
{
(*manip.pf_)(os tr,manip.arg_);
return ostr;
}

template <class charT, class Traits>
inline basic_ostream<c harT,Traits>&
sfmt(basic_ostr eam<charT,Trait s>& ostr, const char* f)
{
CMyStream<charT ,Traits>* p;
try {
p = dynamic_cast<CM yStream<charT,T raits>*>(&ostr) ;
}
catch (std::bad_cast) {
return ostr;
}

p->format(f);
return ostr;
}

template <class charT,class Traits>
inline osmanip<basic_o stream<charT, Traits>,const char*>
setfmt(const char* fmt)
{
return osmanip<basic_o stream<charT,Tr aits>,const char*>(sfmt,fmt );
}

#endif /* __MY_STREAM_CPP */

// mystream_test.c pp
#include "mystream.h "

int
main(int argc, char *argv[])
{
CMyStream<chars trm(std::cout);

strm << "Hello World!" << std::endl;
strm << "123 " << 123 << std::endl;

strm << setfmt<char>("E RROR") << "Byeee" << std::endl;

return 0;
}
Jun 27 '08 #1
6 2605
On Jun 17, 4:19*pm, Dan Smithers <dsmith...@talk talk.netwrote:
I want to write my own class derived from the ostream class.

I have been getting errors with my templates:

First, I get an error writing a nested template. If I leave the function
definition inside template class definition (commented out at //1) then
it compiles and runs fine, but if I declare and define the function
separately (at //2).

Is the following syntax supported by g++?
template<typena me charT, typename Traits>
template<typena me T>
as I get the compiler error
"mystream.cpp:4 7: error: too many template-parameter-lists"

I can't get the use_facet command to work (commented out at //3) as I no
longer have visibility of ostr for getloc and can't call it on my
derived class. Is there another way of achieving this?

I can't get the manipulator function / object combination to compile.
"mystream_test. cpp:11: error: no matching function for call to
‘setfmt(const char [6])’"
Do I need to explicitly qualify the template?

Finally, the compiler seems to get confused by the output operator in
the manipulator (at //4) and issues the following warning:
"mystream.h :41: warning: friend declaration ‘Ostream&
operator<<(Ostr eam&, const osmanip<Ostream , Arg>&)’ declares a
non-template function
mystream.h:41: warning: (if this is not what you intended, make sure the
function template has already been declared and add <after the
function name here) -Wno-non-template-friend disables this warning"

Are these problems due to my own misunderstandin g of templates?

thanks

dan

I have written my templates in three file (mystream.h, mystream.cpp and
mystream_test.c pp) and compiling with g++ 4.2.3

// mystream.h
#include <iostream>
#ifndef __MY_STREAM_H
#define __MY_STREAM_H

template <typename charT, typename Traits=std::cha r_traits<charT
class CMyStream : virtual public std::basic_ostr eam<charT, Traits>
{
public:
* charT *m_fmt;

public:
* // constructor
* CMyStream(std:: basic_ostream<c harT, Traits>& ostr, const char *fmt);
* // destructor
* ~CMyStream();
* // change format string
* std::basic_ostr eam<charT, Traits>& format(const char *fmt);
* // retrieve format string
* charT *format() const;

* // output operator
* template<typena me T>
* friend CMyStream& operator<<(CMyS tream& ostr, T val); //1
// * {
// * * (std::basic_ost ream<charT, Traits>&)ostr << ostr.m_fmt << " ";
// * * (std::basic_ost ream<charT, Traits>&)ostr << val;
// * }

};

template <class Ostream, class Arg>
class osmanip {
public:
* osmanip(Ostream & (*pf)(Ostream&, Arg), Arg arg);

protected:
* Ostream& * * (*pf_)(Ostream& , Arg);
* Arg * * * * *arg_;

* friend Ostream&
* operator<< (Ostream& ostr, const osmanip<Ostream ,Arg>& manip);

};

template <class Ostream, class Arg>
Ostream&
operator<< (Ostream& ostr, const osmanip<Ostream , Arg>& manip);

template <class charT, class Traits>
inline std::basic_ostr eam<charT,Trait s>&
sfmt(std::basic _ostream<charT, Traits>& ostr, const char* f);

template <class charT, class Traits>
inline osmanip<std::ba sic_ostream<cha rT, Traits>, const char*>
setfmt(const char* fmt);

#include "mystream.c pp"

#endif /* __MY_STREAM_H */

// mystream.cpp
#include "mystream.h "

#ifndef __MY_STREAM_CPP
#define __MY_STREAM_CPP

using std::basic_ostr eam;
using std::use_facet;
using std::ctype;

template <typename charT, typename Traits>
CMyStream<charT , Traits>::CMyStr eam(basic_ostre am<charT, Traits>& ostr,
* * * * * * * * * * * * * * * * * * const char *fmt = "log")
* : std::ostream(os tr.rdbuf())
{
* m_fmt = new charT[strlen(fmt)];
* use_facet<ctype <charT(ostr.get loc()).widen(fm t, fmt+strlen(fmt) ,
m_fmt);

}

template <typename charT, typename Traits>
CMyStream<charT , Traits>::~CMySt ream()
{
* delete[] m_fmt;

}

template <typename charT, typename Traits>
basic_ostream<c harT, Traits>&
CMyStream<charT , Traits>::format (const char *fmt)
{
* delete[] m_fmt;
* m_fmt = new charT[strlen(fmt)];
// *use_facet<ctyp e<charT(ostr.ge tloc()).widen(f mt, fmt+strlen(fmt) ,
m_fmt); //3
* return *this;

}

template <typename charT, typename Traits>
charT *
CMyStream<charT , Traits>::format () const
{
* charT *p = new charT[Traits::length( m_fmt)];
* Traits::copy(p, m_fmt, Traits::length( m_fmt));
* return p;

}

template <typename charT, typename Traits=std::cha r_traits<charT
template<typena me T>
CMyStream<charT , Traits>& operator<<(CMyS tream<charT, Traits>& ostr, //2
* * * * * * * * * * * * * * * * * * *T val)
{
* (basic_ostream< charT, Traits>&)ostr << ostr.m_fmt << " ";
* (basic_ostream< charT, Traits>&)ostr << val;

}

template <class Ostream, class Arg>
osmanip<Ostream , Arg>::osmanip(O stream& (*pf)(Ostream&, Arg), Arg arg)
* : pf_(pf) , arg_(arg)
{
* ;

}

//4
template <class Ostream, class Arg>
Ostream& operator<< (Ostream& ostr, const osmanip<Ostream , Arg>& manip)
{
* *(*manip.pf_)(o str,manip.arg_) ;
* *return ostr;

}

template <class charT, class Traits>
inline basic_ostream<c harT,Traits>&
sfmt(basic_ostr eam<charT,Trait s>& ostr, const char* f)
{
* CMyStream<charT ,Traits>* p;
* try {
* * p = dynamic_cast<CM yStream<charT,T raits>*>(&ostr) ;
* }
* catch (std::bad_cast) {
* * * return ostr;
* }

* p->format(f);
* return ostr;

}

template <class charT,class Traits>
inline osmanip<basic_o stream<charT, Traits>,const char*>
setfmt(const char* fmt)
{
* return osmanip<basic_o stream<charT,Tr aits>,const char*>(sfmt,fmt );

}

#endif /* __MY_STREAM_CPP */

// mystream_test.c pp
#include "mystream.h "

int
main(int argc, char *argv[])
{
* CMyStream<chars trm(std::cout);

* strm << "Hello World!" << std::endl;
* strm << "123 " << 123 << std::endl;

* strm << setfmt<char>("E RROR") << "Byeee" << std::endl;

* return 0;

}- Hide quoted text -

- Show quoted text -
Hello,

If i am correct, setfmt template has two template parameters, while
one is alone used when called.
Also, you may want to replace this
template <typename charT, typename Traits=std::cha r_traits<charT

with

template <typename charT, class Traits=std::cha r_traits<charT

I didn't get why would want to write another stream for char when its
already available.

Thanks,
Balaji.
Jun 27 '08 #2
Thanks Balaji,

ka************* ******@gmail.co m wrote:
On Jun 17, 4:19 pm, Dan Smithers <dsmith...@talk talk.netwrote:
>I want to write my own class derived from the ostream class.

I have been getting errors with my templates:

First, I get an error writing a nested template. If I leave the function
definition inside template class definition (commented out at //1) then
it compiles and runs fine, but if I declare and define the function
separately (at //2).

Is the following syntax supported by g++?
template<typen ame charT, typename Traits>
template<typen ame T>
as I get the compiler error
"mystream.cpp: 47: error: too many template-parameter-lists"

I can't get the use_facet command to work (commented out at //3) as I no
longer have visibility of ostr for getloc and can't call it on my
derived class. Is there another way of achieving this?

I can't get the manipulator function / object combination to compile.
"mystream_test .cpp:11: error: no matching function for call to
‘setfmt(cons t char [6])’"
Do I need to explicitly qualify the template?

Finally, the compiler seems to get confused by the output operator in
the manipulator (at //4) and issues the following warning:
"mystream.h:41 : warning: friend declaration ‘Ostream&
operator<<(Ost ream&, const osmanip<Ostream , Arg>&)’ declares a
non-template function
mystream.h:4 1: warning: (if this is not what you intended, make sure the
function template has already been declared and add <after the
function name here) -Wno-non-template-friend disables this warning"

Are these problems due to my own misunderstandin g of templates?

thanks

dan

I have written my templates in three file (mystream.h, mystream.cpp and
mystream_test. cpp) and compiling with g++ 4.2.3

// mystream.h
#include <iostream>
#ifndef __MY_STREAM_H
#define __MY_STREAM_H

template <typename charT, typename Traits=std::cha r_traits<charT
class CMyStream : virtual public std::basic_ostr eam<charT, Traits>
{
public:
charT *m_fmt;

public:
// constructor
CMyStream(std:: basic_ostream<c harT, Traits>& ostr, const char *fmt);
// destructor
~CMyStream();
// change format string
std::basic_ostr eam<charT, Traits>& format(const char *fmt);
// retrieve format string
charT *format() const;

// output operator
template<typena me T>
friend CMyStream& operator<<(CMyS tream& ostr, T val); //1
// {
// (std::basic_ost ream<charT, Traits>&)ostr << ostr.m_fmt << " ";
// (std::basic_ost ream<charT, Traits>&)ostr << val;
// }

};

template <class Ostream, class Arg>
class osmanip {
public:
osmanip(Ostream & (*pf)(Ostream&, Arg), Arg arg);

protected:
Ostream& (*pf_)(Ostream& , Arg);
Arg arg_;

friend Ostream&
operator<< (Ostream& ostr, const osmanip<Ostream ,Arg>& manip);

};

template <class Ostream, class Arg>
Ostream&
operator<< (Ostream& ostr, const osmanip<Ostream , Arg>& manip);

template <class charT, class Traits>
inline std::basic_ostr eam<charT,Trait s>&
sfmt(std::basi c_ostream<charT ,Traits>& ostr, const char* f);

template <class charT, class Traits>
inline osmanip<std::ba sic_ostream<cha rT, Traits>, const char*>
setfmt(const char* fmt);

#include "mystream.c pp"

#endif /* __MY_STREAM_H */

// mystream.cpp
#include "mystream.h "

#ifndef __MY_STREAM_CPP
#define __MY_STREAM_CPP

using std::basic_ostr eam;
using std::use_facet;
using std::ctype;

template <typename charT, typename Traits>
CMyStream<char T, Traits>::CMyStr eam(basic_ostre am<charT, Traits>& ostr,
const char *fmt = "log")
: std::ostream(os tr.rdbuf())
{
m_fmt = new charT[strlen(fmt)];
use_facet<ctype <charT(ostr.get loc()).widen(fm t, fmt+strlen(fmt) ,
m_fmt);

}

template <typename charT, typename Traits>
CMyStream<char T, Traits>::~CMySt ream()
{
delete[] m_fmt;

}

template <typename charT, typename Traits>
basic_ostream< charT, Traits>&
CMyStream<char T, Traits>::format (const char *fmt)
{
delete[] m_fmt;
m_fmt = new charT[strlen(fmt)];
// use_facet<ctype <charT(ostr.get loc()).widen(fm t, fmt+strlen(fmt) ,
m_fmt); //3
return *this;

}

template <typename charT, typename Traits>
charT *
CMyStream<char T, Traits>::format () const
{
charT *p = new charT[Traits::length( m_fmt)];
Traits::copy(p, m_fmt, Traits::length( m_fmt));
return p;

}

template <typename charT, typename Traits=std::cha r_traits<charT
template<typen ame T>
CMyStream<char T, Traits>& operator<<(CMyS tream<charT, Traits>& ostr, //2
T val)
{
(basic_ostream< charT, Traits>&)ostr << ostr.m_fmt << " ";
(basic_ostream< charT, Traits>&)ostr << val;

}

template <class Ostream, class Arg>
osmanip<Ostrea m, Arg>::osmanip(O stream& (*pf)(Ostream&, Arg), Arg arg)
: pf_(pf) , arg_(arg)
{
;

}

//4
template <class Ostream, class Arg>
Ostream& operator<< (Ostream& ostr, const osmanip<Ostream , Arg>& manip)
{
(*manip.pf_)(os tr,manip.arg_);
return ostr;

}

template <class charT, class Traits>
inline basic_ostream<c harT,Traits>&
sfmt(basic_ost ream<charT,Trai ts>& ostr, const char* f)
{
CMyStream<charT ,Traits>* p;
try {
p = dynamic_cast<CM yStream<charT,T raits>*>(&ostr) ;
}
catch (std::bad_cast) {
return ostr;
}

p->format(f);
return ostr;

}

template <class charT,class Traits>
inline osmanip<basic_o stream<charT, Traits>,const char*>
setfmt(const char* fmt)
{
return osmanip<basic_o stream<charT,Tr aits>,const char*>(sfmt,fmt );

}

#endif /* __MY_STREAM_CPP */

// mystream_test.c pp
#include "mystream.h "

int
main(int argc, char *argv[])
{
CMyStream<chars trm(std::cout);

strm << "Hello World!" << std::endl;
strm << "123 " << 123 << std::endl;

strm << setfmt<char>("E RROR") << "Byeee" << std::endl;

return 0;

}- Hide quoted text -

- Show quoted text -

Hello,

If i am correct, setfmt template has two template parameters, while
one is alone used when called.
Also, you may want to replace this
template <typename charT, typename Traits=std::cha r_traits<charT

with

template <typename charT, class Traits=std::cha r_traits<charT
I thought that class and typename were synonymous in this context.
>
I didn't get why would want to write another stream for char when its
already available.
The reason why I'm doing this is that I have a log class that opens a
file and sends a string together with time information to it. My initial
implementation used a method log(const string& msg) to do this, but that
means that I have to pre-format the string.

ostringstream oss;
oss << "log message" << log_val ...;
my_log(oss.str( ));

If I make my log class inherit from ostream then I can simply write

my_log << "log_messag e" << log_val ...;

I thought that while I was doing this I would set up a manipulator so
that I can writethings like
my_log << setformat(Error ) << "error message" << err_code;

my_log << setformat(Warni ng) << "warning message << warning_data;

thanks

dan
Jun 27 '08 #3
Hello,

Dan Smithers wrote:
I want to write my own class derived from the ostream class.

I have been getting errors with my templates:

First, I get an error writing a nested template. If I leave the
function definition inside template class definition (commented out at
//1) then it compiles and runs fine, but if I declare and define the
function separately (at //2).
See the corrections below. I've tried to omit the friends where
possible. I have introduce a new public member.
>
Is the following syntax supported by g++?
template<typena me charT, typename Traits>
template<typena me T>
as I get the compiler error
"mystream.cpp:4 7: error: too many template-parameter-lists"
This happens with template methods of template classes only, you want to
write a free template function, so this should be one list, just
include the typename T in the first list.

>
I can't get the use_facet command to work (commented out at //3) as I
no longer have visibility of ostr for getloc and can't call it on my
derived class. Is there another way of achieving this?
This is due to two-phase lookup. The ostr at that place was not declared
anyway, but just using getloc() within the stream class does not work
either, it has to be this->getloc() to tell the compiler that the
function will be available at instantiation of the template.
>
I can't get the manipulator function / object combination to compile.
"mystream_test. cpp:11: error: no matching function for call to
?setfmt(const char [6])?"
Do I need to explicitly qualify the template?
Yes, you have without more changes. The problem is that the template
parameters for the output osmanip instance cannot be derived from input
parameters alone. The input is always const char*. You probably will
have to use a common osmanip for all streams and distinguish the
streams your manipulator can act on dynamically.
>
Finally, the compiler seems to get confused by the output operator in
the manipulator (at //4) and issues the following warning:
"mystream.h :41: warning: friend declaration ?Ostream&
operator<<(Ostr eam&, const osmanip<Ostream , Arg>&)? declares a
non-template function
mystream.h:41: warning: (if this is not what you intended, make sure
the function template has already been declared and add <after the
function name here) -Wno-non-template-friend disables this warning"

Are these problems due to my own misunderstandin g of templates?
Some I think yes. I have some feeling your are following manuals for
some pre-standard compiler or streams library. You can expect that some
things do not work out of the box.

There have been books written just on getting the stuff with streams and
locales right, there are cans full of worms and lots of errors to get
easily caught by. There are existing libraries for logging I would
consider first before rolling my own.

I have put all your code into one file with a few comments and tried to
get it running, see below.

I hope some of the experts on this can help if I have missed something,
especially on getting the manipulator right without the need to
qualify.

HTH,

Bernd Strieder


############### ############### ############### ############### ####
// mystream.h
#include <iostream>
#ifndef __MY_STREAM_H
#define __MY_STREAM_H

template <typename charT, typename Traits=std::cha r_traits<charT
class CMyStream;

template <typename charT, typename Traits >
class CMyStream : virtual public std::basic_ostr eam<charT, Traits>
{
public:
charT *m_fmt;

public:
// constructor
CMyStream(std:: basic_ostream<c harT, Traits>& ostr, const char *fmt);
// destructor
~CMyStream();
// change format string
std::basic_ostr eam<charT, Traits>& format(const char *fmt);
// retrieve format string
charT *format() const;

};

template <class Ostream, class Arg>
class osmanip;
template <class Ostream, class Arg>
Ostream&
operator<< (Ostream& ostr, const osmanip<Ostream , Arg>& manip);

template <class Ostream, class Arg>
class osmanip {
public:
osmanip(Ostream & (*pf)(Ostream&, Arg), Arg arg);

Ostream& manipulate(Ostr eam&) const;
protected:
Ostream& (*pf_)(Ostream& , Arg);
Arg arg_;

};
template <class charT, class Traits>
inline std::basic_ostr eam<charT,Trait s>&
sfmt(std::basic _ostream<charT, Traits>& ostr, const char* f);

template <class charT, class Traits>
inline osmanip<std::ba sic_ostream<cha rT, Traits>, const char*>
setfmt(const char* fmt);

//#include "mystream.c pp"`

#endif /* __MY_STREAM_H */

// mystream.cpp
//#include "mystream.h "

#ifndef __MY_STREAM_CPP
#define __MY_STREAM_CPP

using std::basic_ostr eam;
using std::use_facet;
using std::ctype;

template <typename charT, typename Traits>
CMyStream<charT , Traits>::CMyStr eam(basic_ostre am<charT, Traits>& ostr,
const char *fmt = "log")
: std::ostream(os tr.rdbuf())
{
m_fmt = new charT[strlen(fmt)];
use_facet<ctype <charT(ostr.get loc()).widen(fm t, fmt+strlen(fmt) ,
m_fmt);
}

template <typename charT, typename Traits>
CMyStream<charT , Traits>::~CMySt ream()
{
delete[] m_fmt;
}

template <typename charT, typename Traits>
basic_ostream<c harT, Traits>&
CMyStream<charT , Traits>::format (const char *fmt)
{
delete[] m_fmt;
m_fmt = new charT[strlen(fmt)];
use_facet<ctype <charT(this->getloc()).wide n(fmt, fmt+strlen(fmt) ,
m_fmt); //3
return *this;
}

template <typename charT, typename Traits>
charT *
CMyStream<charT , Traits>::format () const
{
charT *p = new charT[Traits::length( m_fmt)];
Traits::copy(p, m_fmt, Traits::length( m_fmt));
return p;
}

template <typename T, typename charT, typename Traits>
CMyStream<charT , Traits>& operator<<(CMyS tream<charT, Traits>& ostr, //2
T val)
{
(basic_ostream< charT, Traits>&)ostr << ostr.m_fmt << " ";
(basic_ostream< charT, Traits>&)ostr << val;
return ostr;
}

template <class Ostream, class Arg>
osmanip<Ostream , Arg>::osmanip(O stream& (*pf)(Ostream&, Arg), Arg arg)
: pf_(pf) , arg_(arg)
{
;
}

template <class Ostream, class Arg>
Ostream&
osmanip<Ostream , Arg>::manipulat e(Ostream& ostr) const
{
return (*pf_)(ostr,arg _);
}

//4
template <class Ostream, class Arg>
Ostream& operator<< (Ostream& ostr, const osmanip<Ostream , Arg>& manip)
{
// (*manip.pf_)(os tr,manip.arg_);
// return ostr;
return manip.manipulat e(ostr);
}

template <class charT, class Traits>
inline basic_ostream<c harT,Traits>&
sfmt(basic_ostr eam<charT,Trait s>& ostr, const char* f)
{
CMyStream<charT ,Traits>* p;
try {
p = dynamic_cast<CM yStream<charT,T raits>*>(&ostr) ;
}
catch (std::bad_cast) {
return ostr;
}

p->format(f);
return ostr;
}

template <class charT,class Traits>
inline osmanip<basic_o stream<charT, Traits>,const char*>
setfmt(const char* fmt)
{
return osmanip<basic_o stream<charT,Tr aits>,const char*>(sfmt,fmt );
}

#endif /* __MY_STREAM_CPP */

// mystream_test.c pp
//#include "mystream.h "

int
main(int argc, char *argv[])
{
CMyStream<chars trm(std::cout);

strm << "Hello World!" << std::endl;
strm << "123 " << 123 << std::endl;

strm << setfmt<char, std::char_trait s<char("ERROR" ) << "Byeee" <<
std::endl;

return 0;
}

Jun 27 '08 #4
On Jun 17, 3:22 pm, Dan Smithers <dsmith...@talk talk.netwrote:
kasthurirangan. bal...@gmail.co m wrote:
[...]
Also, you may want to replace this
template <typename charT, typename Traits=std::cha r_traits<charT
with
template <typename charT, class Traits=std::cha r_traits<charT
I thought that class and typename were synonymous in this context.
They are. A lot of experts (but not all) prefer using typename
systematically in this case, to avoid confusion.
I didn't get why would want to write another stream for char
when its already available.
The reason why I'm doing this is that I have a log class that
opens a file and sends a string together with time information
to it.
That's easily done using a forwarding streambuf, see
http://kanze.james.neuf.fr/articles/fltrsbf1.html. More
generally, it is often desirable to make logging configurable,
etc., which often leads to a wrapper (not derivation) around
ostream; there's a generic implementation of this in the code at
my site (along with full implementations of output and input
filtering streambuf): go to the code section, then look up
OutputStreamWra pper in the IO subsection.
My initial implementation used a method log(const
string& msg) to do this, but that means that I have to
pre-format the string.
ostringstream oss;
oss << "log message" << log_val ...;
my_log(oss.str( ));
If I make my log class inherit from ostream then I can simply write
my_log << "log_messag e" << log_val ...;
You can do that with a wrapper as well. And if all you need is
the time stamp, a filtering streambuf means that you're using an
istream; you don't need to inherit (or if you do, it's only to
provide convenience constructors).
I thought that while I was doing this I would set up a
manipulator so that I can writethings like
my_log << setformat(Error ) << "error message" << err_code;
my_log << setformat(Warni ng) << "warning message << warning_data;
This is most often handled by something like:

log( Log::error ) << "message" ... ;
log( Log::warning ) << "message" ... ;

The function "log" determines whether logging at this level is
active or not, and returns a corresponding OutputStreamWra pper.

Note that the destructor of the OutputStreamWra pper here can be
used to force a flush (and ensure that every log message ends
with a new line, if it collaborates with the filtering
streambuf), and the class itself can also grab a lock in its
constructor, and release it in the destructor, to ensure
synchronization in a multi-threaded environment.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #5
Thank you very much Bernd,

I thought that I had tried using this->getloc() during my trials. I
guess that either I had dismissed it as being implicit, or tried it at
the same time as some other "fix" and taken them all out when it didn't
all work.

I see that I had made m_fmt public. If I wanted it private, then
operator<< would need to be a friend, or use an access method. Which is
better?

Can you suggest where I should look for good log libraries?

thanks again

dan
Jun 27 '08 #6
Hello,

Dan Smithers wrote:
Thank you very much Bernd,
You're welcome.
>
I thought that I had tried using this->getloc() during my trials. I
guess that either I had dismissed it as being implicit, or tried it at
the same time as some other "fix" and taken them all out when it
didn't all work.
It is pretty hard to learn that template stuff just by trying and
without working through some textbook. Even worse, you might be faced
with code from different times, when even the textbooks told different
things, or when textbooks on some matter did not exist.

I think what you have tried about iostreams has been tried often enough
and you can find a lot to read about it, but sometimes that stuff does
not hold anymore to the word.
>
I see that I had made m_fmt public. If I wanted it private, then
operator<< would need to be a friend, or use an access method. Which
is better?
IMO it is better to provide some public methods doing just the work you
need on those data members. Then you can avoid most of that friend
business. Those extra public methods could do fine-grained checks, so
it could be public without posing threats.
>
Can you suggest where I should look for good log libraries?
Use keywords "C++ logging library" at a search engine, there are loads
of such libraries. What is good depends on your actual requirements.
Maybe you can find some projects similar to yours and see how they do.

With the danger to become OT here, some thoughts on logging:

If logging is an inherent part of your project, then why not designing
it in an application specific manner, i.e. you design a logging
interface not as generic as the iostreams library, but to your needs.
If you have something to log, then the actual formatting of the message
is arbitrary at that place, while using that operator<< interface to
iostreams concerns you with the actual formatting all over. The best
you can get is a method taking the context info through parameters
creating the log message and routing it to the right place.

And sometimes logging has to be done different depending on the platform
and the language. If you do logging through an application specific
interface, then porting and translating the logging requires work only
behind that interface.

Bernd

Jun 27 '08 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
2831
by: JustSomeGuy | last post by:
I need to write an new class derived from the list class. This class stores data in the list to the disk if an object that is added to the list is over 1K in size. What methods of the std stl list class must Ioverride in order for this to work?
2
5674
by: Julian | last post by:
I would like to have output from my program to be written to cout as well as a file. (actually, i want several other output options but this should explain my problem in the simplest way). I have seen commercial programs print output to the screen as well as to a log file. depending on the user and other situations, i might want to turn off one of the outputs or maybe even both outputs. so, i want a single line with operator << function...
1
1580
by: hitech_guy | last post by:
Hi, I am creating my own class derving from ostream. I am facing problem in compiling with GNU G++ compiler under linux class IWCoreEXPORT IWAFTraceLine : public ostream { public: IWAFTraceLine( const char* pszFileName = 0,int nLine = 0, const char* pszLayer = 0,int nError = -1 ); ~IWAFTraceLine( );
4
2141
by: fabricemarchant | last post by:
Hi ! I've translated Andru Luvisi small LISP interpreter sl3.c http://www.sonoma.edu/users/l/luvisi/sl3.c in C++ in order to understand how it works and to experiment with small LISP. http://fabrice.marchant.free.fr/LISP/slf/060521/ (For now, my C++ code isn't the result of an object analysis, just a
15
4074
by: Nindi73 | last post by:
HI If I define the class DoubleMap such that struct DoubleMap : public std::map<std::string, double>{}; Is there any overhead in calling std::map member functions ? Moreover are STL containers destructors virtual >
3
1593
by: Valerie Hough | last post by:
I would like to derive my own class from the Socket class so that I can pass data from my client socket to the socket Server's OnAccept event.. I tried the syntax : public class MySocketClass: Socket but received a compiler error saying that there had to be arguments to the constructor for my new class. Any help greately appreciated.
7
3109
by: Christopher Pisz | last post by:
I found an article http://spec.winprog.org/streams/ as a starting point, but it seems to do alot of things that aren't very standard at all. One particular problem is, that he is using a vector as his input buffer and trys to assign an iterator to a char pointer. .... class winzoostreambuffer : private LoggerConsole, public sts::basic_streambuf<char, std::char_traits<char>> ....
0
1348
by: James Kanze | last post by:
On 11 avr, 17:44, "mc" <mc_r...@yahoo.comwrote: OK. If the actual format is well documented, that's half the battle won already. Note, however, that reading a float as an int is still very implementation dependent, since the actual internal format of a float varies between machines. The documentation should specify the format of the float in the file, either by reference to some known format (e.g. IEEE), or by explicitely specifying...
3
3428
by: Al Grant | last post by:
Consider two translation units, (1): namespace { struct S { }; } struct D: S { virtual int f(void); }; and (2): #include <typeinfo> struct D; char const *f(D *p) { return typeid(p).name(); }
0
8589
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8287
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8443
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7114
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5548
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4058
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4136
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1757
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1438
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.