tags:

views:

157

answers:

7

Hi! 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: http://stackoverflow.com/questions/2199043/c-operator-overloading-example

Thank you all!

A: 

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) 
cake
A: 

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.

AndreyT
Are you aware of manipulators in C++ streams library?
Alexander Poluektov
Taking in consideration the answer, it doesn't seem so. Though I guess I'm not aware of 'em either!! :D
huff
@Alexander Poluektov: Huh? Yes, I'm aware. Are you? Apparently you have very little idea about the fact that manupulators like `ends` in C++ sterams library work by being *called* with *function call operator* by a dedicated version of `<<` overload.
AndreyT
@huff: You are the one who asked the question, right? So instead of making self-embarassing remarks, I suggest you read the the SO question you linked yourself and see that the manipulator in that question is *called* by *()* operator indirectly, which is how manipulators like that work in such implementations.
AndreyT
@AndreyT: I've just *asked* you (I didn't know whether you were aware or not), but you *made assumption* about me (blaming me not knowing manipulators under-the-hood). Sounds like I've stepped on your foot. Have a nice day buddy.
Alexander Poluektov
@AndreyT: Oh BTW your comment `I don't see any function call operators in **your code**` is totally offtopic then.
Alexander Poluektov
Take it easy. Anyway I don't think I made any self-embarassing remark. Lack of knowledge doesn't have to be embarassing... (as long as it is not because of lacking learning abilities -well, even in that case, it shouldn't...)Well, salud!
huff
@huff: There's no need to pretend that you don't understand what I'm talking about. Lack of knowledge is not self-embarassment. Attacking people (if only with sarcasm) who are trying to help you is self-embarassment.
AndreyT
@Alexander Poluektov: There's no need to strike a pose of "offended innocence". It won't fool anybody here. Everybody understands perfecty well the real meaning of the question you were "just asking".
AndreyT
@AndreyT: Calm down plz. I'm not trying to "fool anybody". From your question anyone could conclude your lack of knowledge of manipulators (and votes for my answer prove it enough). So did I. And that's why I _asked_ you. (And yes, you are a kind of offensive)
Alexander Poluektov
@AndreyT: Though I think you took that comments too dramatically, I'm sorry that you felt attacked. I didn't mean to. Thanks for trying to help. (I still agree with Alexander, anyway)
huff
@Alexander Poluektov: The fact that the only way to invoke a function in C++ is the `()` operator is absolutely undisputable. It is one of the fundamental axioms of C++ language. Period. If you don't (or can't) understand that, then it is too early for you to engage in discussions like this. Now, when someone states this basic axiom and you conclude that they lack knowledge of manipulators (?)... Well, that's just bizzare, to say the least. (As for "votes"... "Votes" on SO don't prove anything at all).
AndreyT
@huff: Apparently, you don't understand. As far as the actual issue is concerned, there's no real disagreement between me and Alexander. What I said is absolutely and undisputably correct. (I'm pretty sure Alexander understands that as well already). It is just that Alexander started to think too much into it and somehow jumped to the conclusion that I'm saying something else, which in fact, I wasn't saying at all. So I'll just repeat it again, since it is important: it is not possible to invoke a function in C++ without using the `()` operator directly or indirectly.
AndreyT
@huff: Other answer have already explained to you how the `()` operator is applied to the manipulator in the case of standard `std::ends` (for one example). This is what you failed to achive, which is why your function is not "executed".
AndreyT
@AndreyT: I agree with him in that, by reading your answer, anyone could conclude lack of knowledge, even if it is not actually the case. What I don't understand is what this argument we're having can achieve.
huff
@huff: No, "anyone" would not conclude that. It takes two things to make such a conclusion: 1) general desire or propencity for "jumping to concusions", and 2) specific inability to recognize the basic truth about the technical matter in question. I agree that lots of people might suffer from this, but certanly not everyone.
AndreyT
@AndreyT::: Ok.
huff
@AndreyT: Apparently you are not the person who could point me which discussions could I engage in, or something like that. Probably you are that kind of person who just _can't_ make mistakes and know _everything_, and thus any _questions_ about their knowledge hurt them _so_ much... Well, I'm not going to continue this flame. BB!
Alexander Poluektov
+1  A: 

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"...)

Adrien Plisson
No, I don't want to use `endl` -I don't want to redefine `endl` either. I want both manipulators to co-exist. I'm still researching on that :D. I'll correct the title to be more accurate.
huff
my wording made me unclear. i understand that you want want both to co-exist, i was just pointing you to the correct name for a construct like `endl`.
Adrien Plisson
Ok. I still can't find the mistake. I don't think it is related to the method storing the `std` manipulators (which was my random guess)... :P
huff
+3  A: 
Nick Meyer
Absolutely true. Anyway, talking about the second part of your answer: why using `ss << std::x;` doesn't still call the manipulator `std::x(ss);`?
huff
@huff, actually, you are correct. If you were creating a manipulator for your own type (like dxfItem) you'd need to use the function call syntax, but since std::ostringstream has its own overload of operator<< for manipulators, you should be able to use the operator.
Nick Meyer
+1  A: 

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.

Alexander Poluektov
+1  A: 

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.

Tadeusz Kopec
+1  A: 

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;
}
Mark B