help-gplusplus
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Problem with deriving from stream templates


From: Dan Smithers
Subject: Problem with deriving from stream templates
Date: Tue, 17 Jun 2008 12:11:51 +0100
User-agent: Thunderbird 2.0.0.14 (X11/20080505)

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;
}


reply via email to

[Prev in Thread] Current Thread [Next in Thread]