1

I have a class "stampstream" that is essentially intended to work like 'cout'. The two functions that follow are outside the class. This is the part that works.

class stampstream: public std::ostream
{
    //code
    stampstream& operator<<(stampstream& (*x)(void))
    {
        //code
    }
    //code
};

stampstream& endr()
{
    //nocode
}

stampstream& (*endrow)(void)=endr;

In main:

stampstream s;
s << "teststring1" << endrow;

Note that "endrow" is essentially 'endl'. This part works perfectly fine, compiles and executes with the right output. Now, I'm trying to overload << with another possible row(int) function. This is the part that doesn't work. Again, it's part of the same class as above and the following 2 functions are outside the class.

class stampstream: public std::ostream
{
    //code
    stampstream& operator<<(stampstream& (*r)(int y))
    {
        //code
    }
    //code
};

stampstream& ro(int y)
{
    //nocode
}

stampstream& (*row)(int)=ro;

In main:

s << "teststring2" << row(5);

This is the error I get:

error: invalid user-defined conversion from ‘stampstream’ to ‘stampstream& (*)(int)’ [-fpermissive]

What am I doing wrong with row ?

15
  • Hint: What is the type of row(5)? Commented Oct 29, 2014 at 2:10
  • row is of type stampstream with int parameter Commented Oct 29, 2014 at 2:12
  • And when you call it, as you do when you say row(5), what does it return? A stampstream, not a pointer to a function. Commented Oct 29, 2014 at 2:13
  • It doesn't return anything, but neither does endrow and that works perfectly fine. Yeah, it's supposed to be a stampstream type return. Commented Oct 29, 2014 at 2:15
  • 1
    It's the "function call operator". It appears to the right of a function or pointer-to-function, calls it immediately, and evaluates to the result (return) of the function call. If you want s << row(5) to work, then row(5) needs to return something that operator<< can accept. Commented Oct 29, 2014 at 2:22

2 Answers 2

3

The problem is that in

s << "teststring2" << row(5);

function call has higher precedence than <<, so this calls the function row points at and then tries to pass its return value (a stampstream &) to operator<<.

What you want is

s << "teststring2" << row;

This doesn't call the function and instead passes the pointer to operator<<. Inside that function, when you want to call x, you'll need to provide the argument.

It sounds like what you are trying to do is to have a function row that creates a functor object that you can then pass to operator<<. You can do that in C++11 with a lambda:

class stampstream: public std::ostream
{
    //code
    stampstream& operator<<(std::function<stampstream&(void)> r)
    {
        //code
    }
    //code
};

std::function<stampstream&(void)> row(int x)
{
    return [x]()->stampstream & {
        //code
    }
}

Which you can call as:

s << "teststring2" << row(5);

The call to row happens first, which constructs a lambda and returns it (but doesn't yet run the code in it). The functor is passed to operator<< and when that function calls r, it will call the code in the lambda (which can refer to the x param, which was bound by value, so copied into the lambda.)

Sign up to request clarification or add additional context in comments.

7 Comments

I got a bunch of errors, but mainly this brings me back to: error: ‘row’ was not declared in this scope... since I'd assume it doesn't have the stampstream type.
'a bunch of errors' probably indicates your compiler doesn't support C++11
I'm using the g++ compiler. I tried g++ -std=c++11... This is what I'm getting: error: declaration of ‘operator<<’ as non-function stampstream& operator<<(std::function<stampstream&(void)> r). error: expected ‘;’ at end of member declaration. error: expected ‘)’ before ‘<’ token. error: ‘function’ in namespace ‘std’ does not name a template type std::function<stampstream&(void)> row(int x). stampstream.cpp: In function ‘int main()’: error: ‘row’ was not declared in this scope s << "teststring2" << row(5).
@Prasad You also need to #include <functional>.
Thank you! It compiles.. Now I'm wondering what I'm supposed to have after return [x]()->stampstream & {... what I'm trying to do requires a private class member data. Also how do I use the parameter 5 passed into row 5 inside the class under the overloaded << ? Wouldn't the parameter need to be passed all the way to the operator overloader?
|
2

Since Chris has already answered your question, I wanted to advise you of alternatives to your current method:

  1. Your stampstream class should use a specialized std::streambuf that writes out the stamp inside overflow(). There's no need to extend an std::ostream and reimplement the input operators. For an example of how to do this, see this thread.

  2. You seem to be using endrow and row like manipulators. Operator overloads already exist for manipulators that do not take arguments at the call site. You can have endrow take and return an object of type std::ostream&. For row you can have it return a class that overloads the inserter to allow the syntax you want:

    struct row_impl
    {
        row_impl(int row) : row(row) { }
        // Write out the row and return the stream
        friend std::ostream& operator<<(std::ostream& os, row_impl const& rimpl);
    private:
        int row;
    };
    
    std::ostream& operator<<(std::ostream& os, row_impl const& rimpl)
    {
        // This is where the code for your original row() function goes
    }
    
    // write out to and return the stampstream instance
    std::ostream& endrow(std::ostream& os);
    
    row_impl row(int row)
    {
        return row_impl(row);
    }
    

    Now s << endrow and s << row(5) will work without having to add anything to your stampstream class.

1 Comment

That was the original solution proposed.. I wanted to try it alternately. But thank you :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.