want to write outstream operator <<, arguments are more than two different types...

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • ednaswap
    New Member
    • Nov 2009
    • 4

    #1

    want to write outstream operator <<, arguments are more than two different types...

    Hello, C++ experts,

    I am writing a Log class something like below.

    =============== == c++ source code =============== =========

    class Log {
    public:
    Log();
    Log(string _filename);
    ~Log();

    public:
    template<typena me paramT>
    void operator<<(cons t paramT& param)
    {
    ofstream outfile;
    char argument[256] = {0};
    sprintf (argument, "%s", filename.c_str( ));
    outfile.open(ar gument, ios::app);

    outfile << param;
    };

    private:
    string filename;
    };


    =============== == c++ source code =============== =========

    and I use above like

    =============== == c++ source code =============== =========
    Log log("Process.tx t");

    vector<Edge*>:: iterator ei;
    for ( ei = edgeSet.begin() ; ei != edgeSet.end(); ++ei )
    {
    log << (*ei)->GetEdgeID(); // => works, for sure...

    log << "Edge ID: " << (*ei)->GetEdgeID() << " "; // => fails..
    }
    =============== == c++ source code =============== =========

    As you may see, ( log << (*ei)->GetEdgeID(); ) works fine,

    but, ( log << "Edge ID: " << (*ei)->GetEdgeID() << " "; ) just fails...

    clearly because the operator must deal with more than one different output

    types like string, integer, and many other data types...

    What can be the best measures for this?
    Last edited by ednaswap; Nov 10 '09, 01:29 PM. Reason: for better viewing
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    Your operator<< returns void so there's no stream for << (*ei)->GetEdgeID() . The operator<< needs to return an ostream& (not an ostream).

    Code:
    log << "Edge ID: " << (*ei)->GetEdgeID() << " "; // => fails..

    Also, what's the array and the sprintf all about? This is C++ and not C.

    Code:
    template<typename paramT>
    void operator<<(const paramT& param)
    {
    ofstream outfile;
    char argument[256] = {0};
    sprintf (argument, "%s", filename.c_str());
    outfile.open(argument, ios::app);
    
    outfile << param;
    };
    The ofstream should have been created in the constructor that takes a string& as an argument. You might write that constrcutor. Note that filename.c_str( ) is a C string so you still don't need the array or the sprintf.


    That will reduce your operator<< to:

    Code:
    template<typename paramT>
    void operator<<(const paramT& param)
    {
        outfile << param;
    };
    which is now just calling the operator<< of param.

    Therefore, your log class is unnecessary.

    Lastly, operator<< cannot be a member function. The first argument of operator<< has to be an ostream& and if it is a member funciton, the compiler will add a first argument of this. That gives the operator<< a this argument, an ostream& argument, and the param argument. Now you die compiling an operator<< with 3 arguments. Research friend functions.

    Comment

    • ednaswap
      New Member
      • Nov 2009
      • 4

      #3
      Thank you for your kind answer.

      My intention was to write an ostream operator "<<" data stream

      following which could be written to a log file whose name is constructed

      when Log class is being instantiated like Log log("test.txt") ;

      That was why there are codes like

      =============== =============== ====
      ofstream outfile;
      char argument[256] = {0};
      sprintf (argument, "%s", filename.c_str( ));
      outfile.open(ar gument, ios::app);
      =============== =============== ====

      was required.


      But, as you suggested, the operator returns void,

      since I changed the meaning of "<<" into the operator for ofstream

      inside the method. That is, data stream following "<<" are written to

      file(s), making it not necessary to return ostream& object.


      Let me research sometime, and if I come up with an answer, I will

      report here.
      Last edited by ednaswap; Nov 10 '09, 09:40 PM. Reason: for changing content

      Comment

      • ednaswap
        New Member
        • Nov 2009
        • 4

        #4
        Lastly, operator<< cannot be a member function. The first argument of operator<< has to be an ostream& and if it is a member funciton, the compiler will add a first argument of this. That gives the operator<< a this argument, an ostream& argument, and the param argument. Now you die compiling an operator<< with 3 arguments. Research friend functions.
        It looks like I read relevant part in Stroustrup's book. Thank for the tip.

        Comment

        • ednaswap
          New Member
          • Nov 2009
          • 4

          #5
          I work as a natural language processing system designer without

          computer science major background( I majored in English literatures and

          linguistics..). So my problem would have seemed a little bit foolish to

          many of you. At any rate...

          After thinking for a while, I realize that "Log class" was not necessary

          to attain what was shown above. Simply using fstream object may

          fulfill my needs at this moment as following.

          Code:
          ofstream outfile;
          outfile.open("log.txt", ios::out);
          :
              outfile << "future cost from node["<< (*i)->GetNodeID() << "] to [" 
              << (*j)->GetNodeID() << "] :" << dist[(*i)->GetNodeID()][(*j)->GetNodeID()] << endl;
          :
          outfile.close();
          I needed the above bit to implement Floyd-Warshall all pair shortest path
          algorithm and I thought Log class would be convenient to record some
          verbose information during process.

          Thank you.
          Last edited by ednaswap; Nov 12 '09, 04:26 AM. Reason: for convenient viewing

          Comment

          • RRick
            Recognized Expert Contributor
            • Feb 2007
            • 463

            #6
            Try adding the ofstream to your Log class

            A simple way to implement a Log class is by putting the ofstream object in the Log class. This is an HAS-A relation where the Log class has an ofstream object.

            It would look something like

            Code:
            class Log
            {
            public:
                Log( const string & fileName);
                void write( const string & message);
            private:
                ofstream stream_;
            };
            The Log constructor would initialize ofstream with the file name.

            The write method would write a message to the file. The write method could also add extra info like the date and time to the log along with the message.

            This allows you to put the different tasks in only the places where they are needed. For example, write is not interested in opening an ofstream and the constructor is not interested in writing things out. This separation of functionality is one of the things that gives objects great versatility.

            Comment

            Working...