D
Dan Smithers
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:stream(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>:smanip(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<char> strm(std::cout);
strm << "Hello World!" << std::endl;
strm << "123 " << 123 << std::endl;
strm << setfmt<char>("ERROR") << "Byeee" << std::endl;
return 0;
}
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:stream(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>:smanip(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<char> strm(std::cout);
strm << "Hello World!" << std::endl;
strm << "123 " << 123 << std::endl;
strm << setfmt<char>("ERROR") << "Byeee" << std::endl;
return 0;
}