c++ioiomanipmanipulators

Can't understand how to make istream manipulator


I want to make an int32_le_read(x) manipulator that reads binary from a file and writes to x. I implemented the int32_bin_manip class

class bin_manip
{
    public:
     bin_manip();
     ~bin_manip();
     friend std::istream& operator>>(std::istream& is,bin_manip& obj);
     friend std::ostream& operator<<(std::ostream& os, const bin_manip& obj);
     virtual std::ostream& write(std::ostream& os) const = 0;
     virtual std::istream& read(std::istream& is) = 0;
};

class int32_bin_manip : public bin_manip
{
    public:
        int32_t* x;
        int32_bin_manip(int& x);
        std::ostream& write(std::ostream& os) const;
        std::istream& read(std::istream& is);
};

for which operator>> and operator<< exist. How do I make a manipulator for istream of it now? For the ostream manipulator, I just created a function that returns an instance of this class and everything worked fine.

int32_bin_manip write_le_int32(int& x)
{
    return int32_bin_manip(x);
}

But I can't do that with the istream manipulator, because its argument is int32_bin_manip& obj, unlike const int32_bin_manip& obj, which means I can't create a function that returns an instance of int32_bin_manip and use it like istream >> int32_le_read(x), because it will bind the temporary instance to a non-const reference which is forbidden. So how do I need to implement such a manipulator?


Solution

  • You can't bind a non-const lvalue reference to a temporary, but you don't have to since you a not modifying the object itself but instead another object that it's pointing at, so make the operator>> take it by const& too:

    class bin_manip {
    public:
        virtual ~bin_manip() = default; // <- added
        friend std::istream& operator>>(std::istream& is, const bin_manip& obj);
        //                                                ^^^^^ added
        friend std::ostream& operator<<(std::ostream& os, const bin_manip& obj);
    
        virtual std::ostream& write(std::ostream& os) const = 0;
        virtual std::istream& read(std::istream& is) const = 0;
        //                                           ^^^^^ added
    };
    

    Demo