Reputation: 2014
Well, I'm wondering why endd
doesn't seem to execute (though it doesn't generate any error at compilation time).
struct dxfDato
{
dxfDato(int c, string v = 0, int t = 0) { codigo = c; valor = v; tipo = t; }
dxfDato() { }
int tipo;
int codigo;
string valor;
};
class dxfItem
{
private:
std::ostringstream ss;
typedef std::ostream& (*manip)(std::ostream&);
public:
int clase;
string valor;
vector<dxfDato> datos;
vector<dxfItem> hijos;
template <typename T>
dxfItem& operator<<(const T& x)
{
ss << x;
return *this;
}
dxfItem& operator<<(manip x) // to store std manipulators
{
ss << x;
return *this;
}
static dxfItem& endd(dxfItem& i) // specific manipulator 'endd'
{
dxfDato dd;
dd.valor = i.ss.str();
i.datos.push_back(dd);
std::cout << "endd found!" << endl;
return i;
}
};
/* blah blah blah */
dxfItem header;
header
<< 9 << endl << "$ACADVER" << endl << 1 << endl << "AC1500" << endl
<< dxfItem::endd // this apparently doesn't execute anything
<< "other data" << endl
;
This is the last problem that I found while trying to develop something. Last thing was exposed here: C++ Operator overloading example
Thank you all!
Upvotes: 3
Views: 345
Reputation: 40332
You've defined type manip
to be a function that takes a std::ostream
by reference and returns a std::ostream
by reference, but you've defined endd
to take a dxfItem
and return a dxfItem
and dxfItem
does not derive from std::ostream
.
Because of this type mismatch, the compiler is generating a call to the operator<<
template, rather than the manip
overload.
Also, your manip
overload needs to actually call the manipulator function passed into it:
dxfItem& operator<<(manip x)
{
x(ss);
return *this;
}
Upvotes: 4
Reputation: 96281
As previously mentioned the standard streams use an overloaded operator<< that takes a function pointer of the type of the manipulator, and then calls that manipulator to implement the behavior.
The typedef and overloaded operator<< that you provided should allow you to use standard manipulators because the function expected accepts and returns an ostream&.
You didn't declare an overloaded operator<< that takes a function pointer for a function that accepts and returns dxfItem&, so it will use the default operator<< which should just store/print the address of the function rather than executing the manipulator.
You'll need to set up a typedef for your manipulator:
typedef dxfItem& (*endd_manip)(dxfItem&);
Then you can create an overloaded operator<< for it:
dxfItem& operator<<(endd_manip x)
{
// Call the manipulator on the stream.
x(*this);
return *this;
}
Upvotes: 1
Reputation: 12413
Agreeing to Adrien Plisson advice to learn more about manipulators, I can show you how to achieve what I think you want:
typedef dxfItem& (*noArgdxfManip)(dxfItem &); // here is the type for your manipulator
dxfItem & operator << (noArgdxfManip manip)
{
return manip(*this);
}
If you can understand this code, you can understand the trick by which manipulators work. Usually if stream sees a function pointer passed to it with << operator, it just tries to print its content. But there is an overload for function pointers that operate on streams and return streams, which instead of printing pointer invoke pointed function on the stream. Here you do the same for your dxfItem class.
DISCLAIMER I didn't try to compile it so it can contain some syntax errors.
Upvotes: 1
Reputation: 8063
To being called as manipulator, your function should have type std::ostream& (*)(std::ostream& strm)
.
Note that it is not allowed in current C++ to define your own manipulator with parameter.
Upvotes: 1
Reputation: 23303
The syntax you are using when trying to execute endd
makes me think that you want to use it as endl
. endl
is a special construct which is called a manipulator. you can construct your own manipulator, but this is not a topic for the faint-hearted (nor for the beginners).
(anyway, if you still want to make endd
a manipulator, google for "C++ stream manipulator tutorial"...)
Upvotes: 1
Reputation: 320631
Functions in C++ language (as well as in C) are called ("executed") by a function call operator ()
(which can also supply arguments to the function). I don't see any function call operators in your code applied to endd
function, directly or indirectly. This is why it is never executed.
Upvotes: -1
Reputation: 1386
I think that the problem my be that this line
<< dxfItem::endd // this apparently doesn't execute anything
Should be something like this
<< dxfItem::endd(Whatever argument goes in here)
Upvotes: 0