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, or is it a limitation of g++? 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<char> strm(std::cout); strm << "Hello World!" << std::endl; strm << "123 " << 123 << std::endl; strm << setfmt<char>("ERROR") << "Byeee" << std::endl; return 0; } _______________________________________________ help-gplusplus mailing list help-gplusplus@gnu.org http://lists.gnu.org/mailman/listinfo/help-gplusplus