huff
huff

Reputation: 2014

C++ Manipulator not being executed

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

Answers (7)

Nick Meyer
Nick Meyer

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

Mark B
Mark B

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

Tadeusz Kopec for Ukraine
Tadeusz Kopec for Ukraine

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

Alexander Poluektov
Alexander Poluektov

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

Adrien Plisson
Adrien Plisson

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

AnT stands with Russia
AnT stands with Russia

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

cake
cake

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

Related Questions