473,394 Members | 1,726 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

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<typename charT, typename Traits>
template<typename 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(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<<(Ostream&, 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 misunderstanding 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::char_traits<charT
class CMyStream : virtual public std::basic_ostream<charT, Traits>
{
public:
charT *m_fmt;

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

// output operator
template<typename T>
friend CMyStream& operator<<(CMyStream& ostr, T val); //1
// {
// (std::basic_ostream<charT, Traits>&)ostr << ostr.m_fmt << " ";
// (std::basic_ostream<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_ostream<charT,Traits>&
sfmt(std::basic_ostream<charT,Traits>& ostr, const char* f);

template <class charT, class Traits>
inline osmanip<std::basic_ostream<charT, Traits>, const char*>
setfmt(const char* fmt);

#include "mystream.cpp"

#endif /* __MY_STREAM_H */

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

#ifndef __MY_STREAM_CPP
#define __MY_STREAM_CPP

using std::basic_ostream;
using std::use_facet;
using std::ctype;

template <typename charT, typename Traits>
CMyStream<charT, Traits>::CMyStream(basic_ostream<charT, Traits>& ostr,
const char *fmt = "log")
: std::ostream(ostr.rdbuf())
{
m_fmt = new charT[strlen(fmt)];
use_facet<ctype<charT(ostr.getloc()).widen(fmt, fmt+strlen(fmt),
m_fmt);
}

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

template <typename charT, typename Traits>
basic_ostream<charT, Traits>&
CMyStream<charT, Traits>::format(const char *fmt)
{
delete[] m_fmt;
m_fmt = new charT[strlen(fmt)];
// use_facet<ctype<charT(ostr.getloc()).widen(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 charT, typename Traits=std::char_traits<charT
template<typename T>
CMyStream<charT, Traits>& operator<<(CMyStream<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(Ostream& (*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_)(ostr,manip.arg_);
return ostr;
}

template <class charT, class Traits>
inline basic_ostream<charT,Traits>&
sfmt(basic_ostream<charT,Traits>& ostr, const char* f)
{
CMyStream<charT,Traits>* p;
try {
p = dynamic_cast<CMyStream<charT,Traits>*>(&ostr);
}
catch (std::bad_cast) {
return ostr;
}

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

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

#endif /* __MY_STREAM_CPP */

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

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

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

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

return 0;
}
Jun 27 '08 #1
6 2584
On Jun 17, 4:19*pm, Dan Smithers <dsmith...@talktalk.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<typename charT, typename Traits>
template<typename 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(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<<(Ostream&, 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 misunderstanding 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::char_traits<charT
class CMyStream : virtual public std::basic_ostream<charT, Traits>
{
public:
* charT *m_fmt;

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

* // output operator
* template<typename T>
* friend CMyStream& operator<<(CMyStream& ostr, T val); //1
// * {
// * * (std::basic_ostream<charT, Traits>&)ostr << ostr.m_fmt << " ";
// * * (std::basic_ostream<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_ostream<charT,Traits>&
sfmt(std::basic_ostream<charT,Traits>& ostr, const char* f);

template <class charT, class Traits>
inline osmanip<std::basic_ostream<charT, Traits>, const char*>
setfmt(const char* fmt);

#include "mystream.cpp"

#endif /* __MY_STREAM_H */

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

#ifndef __MY_STREAM_CPP
#define __MY_STREAM_CPP

using std::basic_ostream;
using std::use_facet;
using std::ctype;

template <typename charT, typename Traits>
CMyStream<charT, Traits>::CMyStream(basic_ostream<charT, Traits>& ostr,
* * * * * * * * * * * * * * * * * * const char *fmt = "log")
* : std::ostream(ostr.rdbuf())
{
* m_fmt = new charT[strlen(fmt)];
* use_facet<ctype<charT(ostr.getloc()).widen(fmt, fmt+strlen(fmt),
m_fmt);

}

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

}

template <typename charT, typename Traits>
basic_ostream<charT, Traits>&
CMyStream<charT, Traits>::format(const char *fmt)
{
* delete[] m_fmt;
* m_fmt = new charT[strlen(fmt)];
// *use_facet<ctype<charT(ostr.getloc()).widen(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 charT, typename Traits=std::char_traits<charT
template<typename T>
CMyStream<charT, Traits>& operator<<(CMyStream<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(Ostream& (*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_)(ostr,manip.arg_);
* *return ostr;

}

template <class charT, class Traits>
inline basic_ostream<charT,Traits>&
sfmt(basic_ostream<charT,Traits>& ostr, const char* f)
{
* CMyStream<charT,Traits>* p;
* try {
* * p = dynamic_cast<CMyStream<charT,Traits>*>(&ostr);
* }
* catch (std::bad_cast) {
* * * return ostr;
* }

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

}

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

}

#endif /* __MY_STREAM_CPP */

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

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

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

* strm << setfmt<char>("ERROR") << "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::char_traits<charT

with

template <typename charT, class Traits=std::char_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.com wrote:
On Jun 17, 4:19 pm, Dan Smithers <dsmith...@talktalk.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<typename charT, typename Traits>
template<typename 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(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<<(Ostream&, 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 misunderstanding 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::char_traits<charT
class CMyStream : virtual public std::basic_ostream<charT, Traits>
{
public:
charT *m_fmt;

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

// output operator
template<typename T>
friend CMyStream& operator<<(CMyStream& ostr, T val); //1
// {
// (std::basic_ostream<charT, Traits>&)ostr << ostr.m_fmt << " ";
// (std::basic_ostream<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_ostream<charT,Traits>&
sfmt(std::basic_ostream<charT,Traits>& ostr, const char* f);

template <class charT, class Traits>
inline osmanip<std::basic_ostream<charT, Traits>, const char*>
setfmt(const char* fmt);

#include "mystream.cpp"

#endif /* __MY_STREAM_H */

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

#ifndef __MY_STREAM_CPP
#define __MY_STREAM_CPP

using std::basic_ostream;
using std::use_facet;
using std::ctype;

template <typename charT, typename Traits>
CMyStream<charT, Traits>::CMyStream(basic_ostream<charT, Traits>& ostr,
const char *fmt = "log")
: std::ostream(ostr.rdbuf())
{
m_fmt = new charT[strlen(fmt)];
use_facet<ctype<charT(ostr.getloc()).widen(fmt, fmt+strlen(fmt),
m_fmt);

}

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

}

template <typename charT, typename Traits>
basic_ostream<charT, Traits>&
CMyStream<charT, Traits>::format(const char *fmt)
{
delete[] m_fmt;
m_fmt = new charT[strlen(fmt)];
// use_facet<ctype<charT(ostr.getloc()).widen(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 charT, typename Traits=std::char_traits<charT
template<typename T>
CMyStream<charT, Traits>& operator<<(CMyStream<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(Ostream& (*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_)(ostr,manip.arg_);
return ostr;

}

template <class charT, class Traits>
inline basic_ostream<charT,Traits>&
sfmt(basic_ostream<charT,Traits>& ostr, const char* f)
{
CMyStream<charT,Traits>* p;
try {
p = dynamic_cast<CMyStream<charT,Traits>*>(&ostr);
}
catch (std::bad_cast) {
return ostr;
}

p->format(f);
return ostr;

}

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

}

#endif /* __MY_STREAM_CPP */

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

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

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

strm << setfmt<char>("ERROR") << "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::char_traits<charT

with

template <typename charT, class Traits=std::char_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_message" << 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(Warning) << "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<typename charT, typename Traits>
template<typename T>
as I get the compiler error
"mystream.cpp:47: 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<<(Ostream&, 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 misunderstanding 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::char_traits<charT
class CMyStream;

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

public:
// constructor
CMyStream(std::basic_ostream<charT, Traits>& ostr, const char *fmt);
// destructor
~CMyStream();
// change format string
std::basic_ostream<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(Ostream&) const;
protected:
Ostream& (*pf_)(Ostream&, Arg);
Arg arg_;

};
template <class charT, class Traits>
inline std::basic_ostream<charT,Traits>&
sfmt(std::basic_ostream<charT,Traits>& ostr, const char* f);

template <class charT, class Traits>
inline osmanip<std::basic_ostream<charT, Traits>, const char*>
setfmt(const char* fmt);

//#include "mystream.cpp"`

#endif /* __MY_STREAM_H */

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

#ifndef __MY_STREAM_CPP
#define __MY_STREAM_CPP

using std::basic_ostream;
using std::use_facet;
using std::ctype;

template <typename charT, typename Traits>
CMyStream<charT, Traits>::CMyStream(basic_ostream<charT, Traits>& ostr,
const char *fmt = "log")
: std::ostream(ostr.rdbuf())
{
m_fmt = new charT[strlen(fmt)];
use_facet<ctype<charT(ostr.getloc()).widen(fmt, fmt+strlen(fmt),
m_fmt);
}

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

template <typename charT, typename Traits>
basic_ostream<charT, Traits>&
CMyStream<charT, Traits>::format(const char *fmt)
{
delete[] m_fmt;
m_fmt = new charT[strlen(fmt)];
use_facet<ctype<charT(this->getloc()).widen(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<<(CMyStream<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(Ostream& (*pf)(Ostream&, Arg), Arg arg)
: pf_(pf) , arg_(arg)
{
;
}

template <class Ostream, class Arg>
Ostream&
osmanip<Ostream, Arg>::manipulate(Ostream& ostr) const
{
return (*pf_)(ostr,arg_);
}

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

template <class charT, class Traits>
inline basic_ostream<charT,Traits>&
sfmt(basic_ostream<charT,Traits>& ostr, const char* f)
{
CMyStream<charT,Traits>* p;
try {
p = dynamic_cast<CMyStream<charT,Traits>*>(&ostr);
}
catch (std::bad_cast) {
return ostr;
}

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

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

#endif /* __MY_STREAM_CPP */

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

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

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

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

return 0;
}

Jun 27 '08 #4
On Jun 17, 3:22 pm, Dan Smithers <dsmith...@talktalk.netwrote:
kasthurirangan.bal...@gmail.com wrote:
[...]
Also, you may want to replace this
template <typename charT, typename Traits=std::char_traits<charT
with
template <typename charT, class Traits=std::char_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
OutputStreamWrapper 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_message" << 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(Warning) << "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 OutputStreamWrapper.

Note that the destructor of the OutputStreamWrapper 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 objektorientierter Datenverarbeitung
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
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...
2
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...
1
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:...
4
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....
15
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...
3
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:...
7
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...
0
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...
3
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...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
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...
0
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...
0
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...

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.