   formatting with C++
  HiI really wish I could find the answer myself, but I couldn't get it from nowhere. So you guys are my only hope :(.Well I have one class and I want it to accept some kind of string and output it either to file,console or both.(Something like log):Quote://this is good choice - but not actually working with string rather with char*//and causes nasty exception when string is inserted as char*. // off course I can use c_str() - But I am looking for C++ way.log.Write("Data is = %s", data.Status());//another way// This is a good way, but I can't seems to get it workinglog << "Data is =%s" << data.Status();//and this method also - good but not workinglog.Write("Data is =",data.Status() );//or log.Write("Data is =" << data.Status() );Actually each log.Write should call my function pointer, which does additional actions with message, depending from selected mode.I have problem with overloading << operator, and with other possible versions.I want to call my function once the data is parsed into string, or somewhere else. But as I understand << works multiple times passing previous result to other argument.Thank you I hope some one can help me out with this.   
  Try to avoid the ellipse construct.  What problems are you having overloading the << operator?   ;  If the only method your log class has is Write( const char* fmt... ) then the only option you have is  log.Write("Data is = %s", data.Status().c_str());However, if you can change the log class -- introduce some kind of streaming operators (like operator<<) and/or take a look to boost::format library.   ;  I am not going to use boost.The thing is that I want to have << method or others but not C style.The problem with << is that I want it to run my function pointer, once all parts are parsed. Here is current not working version:   template <class T>   std::ofstream& operator << (T& obj)   { _fout <<  obj;   //I need to call the function pointer    //and pass the string   (this->*out)(_fout);   return _fout; };Quote:Original post by DMINATORI am not going to use boost.Why not?  Why reinvent the wheel when you don't have to.  You don't say "I'm not going to use the standard library", do you.Anyway.  Assuming that I'm correct in understanding that you want:log << "Data is = " << data.Status();log << "Data is still = " << data.Status(); to have the effect:std::stringstream ss1;ss1 << "Data is = " << data.Status();some_member_function_pointer_call(ss1.str());std::stringstream ss2;ss2 << "Data is still = " << data.Status();some_member_function_pointer_call(ss2.str());You could do something like (fairly off the top of my head.  There may well be better ways):#include <iostream>#include <sstream>#include <string>class Log{class LogLine;public:Log():_fout(&Log::flush){}template < typename Type >LogLine operator<<(Type const & value){LogLine ll(this, _fout);ll << value;return ll;}private:void flush(std::string const & string){std::cout << string << "FLUSHED\n";}typedef void (Log::* LogFunction)(std::string const &);class LogLine{public:typedef void (Log::* LogFunction)(std::string const &);LogLine(Log * log, LogFunction function):log_(log),function_(function),flush_(true){}LogLine(LogLine & ll):log_(ll.log_),function_(ll.function_),flush_(ll.flush_),lineStream_(){lineStream_ << ll.lineStream_.str();ll.flush_ = false;}~LogLine(){if (flush_){(log_->*function_)(lineStream_.str());}}template < typename Type >LogLine & operator<<(Type const & value){lineStream_ << value;return *this;}private:Log * log_;LogFunction function_;bool flush_;std::ostringstream lineStream_;LogLine & operator=(LogLine const & ll);};LogFunction _fout;};int main(){Log log;log << 1 << 2 << 3;log << "This is a line";log << "Hello " << std::string("number ") << 5;}Enigma   ;Quote:Original post by EnigmaQuote:Original post by DMINATORI am not going to use boost.Why not?  Why reinvent the wheel when you don't have to.  You don't say "I'm not going to use the standard library", do you.Anyway.  Assuming that I'm correct in understanding that you want:log << "Data is = " << data.Status();log << "Data is still = " << data.Status(); to have the effect:std::stringstream ss1;ss1 << "Data is = " << data.Status();some_member_function_pointer_call(ss1.str());std::stringstream ss2;ss2 << "Data is still = " << data.Status();some_member_function_pointer_call(ss2.str());You could do something like (fairly off the top of my head.  There may well be better ways):*** Source Snippet Removed ***EnigmaThank you for your advice. About boost, well first I don't want to include additional libraries files with my code, secondly I can't understand a thing how to install this boost . About the wheel - well I can stop programming, or maybe use some already made game engines, OGRE for example. Why bother everything is already made. About the code, I don't understand it either, it is highly complicated for such a simple task (?).Here is how I am currently using C style format:_lbuff is just char[500];//and out is just a function that accepts string as argumenttypedef void (Log::*__Out)(const std::string &message); __Out out;void Log::Write(const char *msg, ...){   va_list args;   va_start(args,msg);   vsprintf(_lbuff,msg,args);   va_end(args);   //now send it to our message   (this->*out)(_lbuff);};Quote:Original post by DMINATORThank you for your advice. About boost, well first I don't want to include additional libraries files with my code, secondly I can't understand a thing how to install this boost.The only really valid reasons for not wanting to add additional libraries are:cross-compiler/cross-platform supportconstantly moving development between (new) machines such that libraries would have to be installed frequentlynot wanting other developers to have to download additional files to use your codeBoost is sufficiently well-known and portable that I don't consider the first or last of those reasons to apply to it.  That leaves only situations where development is constantly moving machines, which is a pretty rare case.  As to how to install Boost, well for most of the libraries it's a case of:Download BoostExtract BoostSet up compiler include path for BoostWhich is about as easy as it gets.  For a few of the libraries you have the additional steps:Download Boost.Jamrun bjam "-sTOOLS=..." where ... is the relevent toolset for your compiler, selected from the Getting Started page.Quote:About the wheel - well I can stop programming, or maybe use some already made game engines, OGRE for example. Why bother everything is already made.You could also build your own microprocessor and write your code in binary, but you don't.  A ready-made engine is a high level abstraction and unless you design for that specific engine it is unlikely that it will exactly meet your requirements and will require some form of modification.  In this case it may be more productive to build your own engine from scratch for reasons of poor documentation, a design which is not easily modified to your needs, etc.  The standard library provides a much lower level of abstraction and it is much more likely to meet your requirements with little or no modification.  Obviously you have to draw the line at some level.  Boost provides a level of abstraction which tends to be only a little higher than the standard library so I view using one and not considering the other to be silly.Quote:About the code, I don't understand it either, it is highly complicated for such a simple task (?).It's not that complicated.  The first time you call operator<< on your log in a statement it creates an unnamed temporary object of type Log::LogLine and the value is redirected into that object.  All subsequent calls to operator<< also act on that object.  At the end of the statement the temporary object is destroyed and its destructor calls the member function pointer you specified.  So the code:log << "Hello " << std::string("number ") << 5;Essentially translates to (pseudocode, not an exact translation):{Log::LogLine temp(log);temp << "Hello ";temp << std::string("number ");temp << 5;temp.~Log::LogLine();}where temp.~Log::LogLine() calls (effectively) (log->*out)(temp.str());.  (I now realise that I'd incorrectly copied the name of your member function pointer as _fout, not out before).There's a little extra work involving the flush_ member variable to handle the case where the temporary object is returned by value (on compilers which don't implement the return value optimization this can result in a copy-construction and a destructor call.  We don't want that destructor call to call the member function pointer).Quote:typedef void (Log::*__Out)(const std::string &message);Naughty.  Identifiers beginning with a double underscore are reserved for compiler and standard library writers.Enigma   ;  Something like this?// First we define this helper class...class LogData {  std::stringstream ss;  Log* logger;  public:  LogData(const Log& l) : ss(), logger(&l) {}  template<typename T>  LogData& operator()(const T& next) { ss << next; return *this; }  void operator()() { logger->Write(ss.str().c_str()); }};// Now the Write function becomes something like...void Log::Write(const char* const data) {  (this->*out)(data);}// and we can use it like this:int main() {  Log l;  LogData(l)("hello ")(std::string("world!!"))(111)();}