Search code examples
c++wrapperofstream

How to wrapper ofstream?


I'm trying to wrapper the standard ofstream, and hope I can do additional compare and output.

Everything goes well, except the std::endl or end used as first output token.

But, when I turn on the #if0 ... #endif block in the main function, the g++ report many errors.

How can I solve it? Is there a alternative solution.

compile command is: g++ test.cpp -std=c++11 -ggdb -o a.out

below is the code

#include <fstream>
#include <iostream>
#include <string>

using namespace std;

class Logger {
 private:
  template <typename T>
  friend ofstream& operator<<(Logger&, T);

  ofstream os_;
  std::string file_name;
  uint32_t count = 0;

 public:
  // Logger(std::string name) : file_name(name), curIndentLevel_(0)
  explicit Logger(const std::string& name) : file_name(name) {
    // open the file and ready to write.
    os_.open(file_name, std::ofstream::out | std::ofstream::app);
  }
};

template <typename T>
inline ofstream& operator<<(Logger& log, T op) {
  // write stream to the target file.

  if ((log.count % 100) == 0) {
    // output a  split token
    log.os_ << "=============" << std::endl;
  }

  log.os_ << ' ';
  log.os_ << op;
  log.os_.flush();
  log.count++;

  return log.os_;
}

class MyClass {
 public:
  uint32_t value = 0xf;
  uint32_t x = 0;
  std::string file_name = "456.txt";

  Logger log = Logger("456.txt");

 public:
  MyClass() {}
  ~MyClass() {}
};

int main() {
  Logger log("123.txt");

  for (uint32_t i = 0; i < 5000; i++) {
    log << "Hello World!" << std::hex << " 0x= " << 100 << ", sdfdsfs"
        << " ABC " << std::dec << " =0x " << 100 << std::endl
        << endl;
  }

#if 0
  // why did the "end" can not be the first element?
  // how to solve it.
  log <<endl;      //errors.
  log <<std::endl;  //errors
  log <<std::endl<< "***** The log execute  successfully."<<std::endl<<std::endl; //errors
#endif

  log << std::dec;
  log << std::hex;

  log << "Hello World!" << std::endl;
  return 0;
}



Solution

  • Just use inheritance directly.

    #include <iostream>
    #include <string>
    #include <fstream>
    
    using namespace std;
    
    class Logger : public ofstream {
    template<typename T> friend Logger& operator<<(Logger&, T);
    public:
        Logger(const string& file_name) {
            open(file_name);
        }
    private:
        uint32_t count = 0;
    };
    
    template<typename T>
    inline Logger& operator<<(Logger& log, T op) {
        //write stream to the target file.
        auto& base_log = static_cast<ofstream&>(log);
        if( (log.count%100) == 0){
            //output a  split token
            base_log << "============="<<std::endl;
        }
        base_log << ' ';
        base_log << op;
        base_log.flush();
    
        log.count++;
        return log;
    }
    
    int main() {
    
        Logger log("123.txt");
    
        for(uint32_t i =0;i<5000;i++){
            log << "Hello World!" <<std::hex<<" 0x= "<<100 <<", sdfdsfs" << " ABC "<<std::dec << " =0x " << 100<<std::endl<<endl; 
        }
    
        log <<endl;
        log <<std::dec; 
        log <<std::hex; 
    
        log << "Hello World!" << std::endl;
        return 0;
    }