Home > Software engineering >  How can I pass these references to the same function?
How can I pass these references to the same function?

Time:07-26

I have a function parse(Stream & in) I'd like to call as both:

// asFile() is a static method that returns a Stream object by value
parse(Stream::asFile("filename.txt"));  

and also

Stream file = Stream::asFile("filename.txt");
parse(file);
file.getPos(); // file retains state set by the parse function  

But it runs into an issue with lvalues or some such.

Is there a way I can write a function so that it will work with both of these parameters?

CodePudding user response:

Is this what you are looking for?

#include <iostream>
#include <string>

// An object to simulate the state of your stream.
// Whatever in here must be movable.
// Here I am relying on default compiler generated move operators.
struct Data
{
    std::string data;
};

// You don't provide a definition of stream.
// This is the minimum you need.
class Stream
{
    Data    data;
    private:
        // Assuming the constructor is private
        // So that you have to use Stream::asFile() to construct
        // a stream object.
        Stream(std::string const& name)
            : data{name}
        {}
    public:
        // Here is your static function.
        static Stream asFile(std::string const& name)
        {
            return Stream(name);
        }

        // Need a public Move Constructor.
        Stream(Stream&& move)
            : data(std::move(move.data))
        {}
};


// Two versions of parse.
// One takes a stream by reference.
// And does the work.
void parse(Stream& stream)
{
    std::cout << "  Parsing Stream\n";
}

// A version of parse that takes an r-value reference.
// Here you take ownership of the stream but simply
// call the standard version of parse (above).
void parse(Stream&& stream)
{
    std::cout << "  Parsing Moved Stream\n";
    parse(stream);
};

// Test Framework that shows both operations.
int main()
{
    std::cout << "Parse using reference\n";
    Stream file = Stream::asFile("filename.txt");
    parse(file);
    // file.stuff()   file still own the resource 
    //                You can call normal methods on it.

    std::cout << "Parse using r-value reference\n";
    parse(Stream::asFile("filename.txt"));
    // This one moves the ownership to the second parse.
}

Running:

Parse using reference
  Parsing Stream
Parse using r-value reference
  Parsing Moved Stream
  Parsing Stream
  • Related