Reputation: 67
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 ?
Upvotes: 1
Views: 600
Reputation: 96810
Since Chris has already answered your question, I wanted to advise you of alternatives to your current method:
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.
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.
Upvotes: 2
Reputation: 126203
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.)
Upvotes: 3