By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,402 Members | 1,127 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,402 IT Pros & Developers. It's quick & easy.

a manipulator wrapped inside a struct/class does not compile

P: n/a
Hello group, this is my dilemma:
------------------------------------------------------------------------

#include <iostream>

using namespace std;

// a regular manipulator
ostream & hello( ostream & os ) { return os << "regular: hello"; }

struct Test // a manipulator wrapped inside a struct
{
ostream & hello( ostream & os ) { return os << "wrapped: hello"; }
};

int main( )
{
cout << hello << endl; // this works just fine..

Test t;
cout << t.hello << endl; // and this doesn't compile! WHY??

/* note: gcc 2.95.4 says there's no matching function to call,
* and then lists the possible applicators; but there it is:
*
* class ostream & ostream::operator <<(ostream & (*)(ostream &))
*
* isn't that the wrapped manipulator's signature?
* I don't get it. Would anyone be so kind to explain? thanks!
*/

return 0;
}

Oct 28 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
st****@gmail.com wrote:
Hello group, this is my dilemma:
------------------------------------------------------------------------

#include <iostream>

using namespace std;

// a regular manipulator
ostream & hello( ostream & os ) { return os << "regular: hello"; }

struct Test // a manipulator wrapped inside a struct
{
ostream & hello( ostream & os ) { return os << "wrapped: hello"; }
A pointer to a function and a pointer to a member function are not
compatible. A manipulator is expected to be a pointer to a function,
not to a member.
};

int main( )
{
cout << hello << endl; // this works just fine..

Test t;
cout << t.hello << endl; // and this doesn't compile! WHY??
Because 't.hello' is a syntax error. You either need 't.hello()' or
'&Test::hello', to make something of 'hello'. And the second one is not
going to fly due to pointer incompatibility I mentioned above. And the
first one is not what you want.
/* note: gcc 2.95.4 says there's no matching function to call,
* and then lists the possible applicators; but there it is:
*
* class ostream & ostream::operator <<(ostream & (*)(ostream &))
*
* isn't that the wrapped manipulator's signature?
* I don't get it. Would anyone be so kind to explain? thanks!
*/

return 0;
}


V
Oct 28 '05 #2

P: n/a
> A pointer to a function and a pointer to a member function are not
compatible. A manipulator is expected to be a pointer to a function,
not to a member.
why is that exactly?
Because 't.hello' is a syntax error. You either need 't.hello()' or
'&Test::hello', to make something of 'hello'. And the second one is not
going to fly due to pointer incompatibility I mentioned above. And the
first one is not what you want.


't.hello()' wouldn't work because the applicator expects a pointer -
not a method.

'&Test::hello' is a pointer to a class method. That's not what I need.
I have an instance method 'hello'.

I can see 't.hello' is a syntax error, but am curious why this is so.
As far as I can see the compiler is reacting as though 'hello' is of
type 'ostream& (Test::*)( ostream& )', but the 'Test::' part is
irrelevant.. I have dereferenced it with a dot after 't' as in:

struct Test
{
int whatever;
} t;

't.whatever' is of type 'int', not 'Test::int'!
So why isn't 't.hello' of type 'ostream&(*)(ostream&)'? Or even
better.. I believe you understand what kind of use I am aiming at.. is
there a way to circumvent this problem?

Thanks!

Oct 28 '05 #3

P: n/a
st****@gmail.com wrote:
A pointer to a function and a pointer to a member function are not
compatible. A manipulator is expected to be a pointer to a function,
not to a member.

why is that exactly?


Why is what exactly? I made two statements, which one are you asking about?
Because 't.hello' is a syntax error. You either need 't.hello()' or
'&Test::hello', to make something of 'hello'. And the second one is not
going to fly due to pointer incompatibility I mentioned above. And the
first one is not what you want.

't.hello()' wouldn't work because the applicator expects a pointer -
not a method.


You can make 'hello' actually return a pointer.
'&Test::hello' is a pointer to a class method. That's not what I need.
I have an instance method 'hello'.
The term is "non-static member function". Perhaps you should start using
it...
I can see 't.hello' is a syntax error, but am curious why this is so.
Because the language was designed that way.
As far as I can see the compiler is reacting as though 'hello' is of
type 'ostream& (Test::*)( ostream& )', but the 'Test::' part is
irrelevant.. I have dereferenced it with a dot after 't' as in:

struct Test
{
int whatever;
} t;

't.whatever' is of type 'int', not 'Test::int'!
So why isn't 't.hello' of type 'ostream&(*)(ostream&)'?
Because. A function name and an object name behave differently when used
in an expression. You _could_ define 'hello' to be a member of "Test" and
have a type "a pointer to function":

struct Test {
ostream& (*hello)(ostream&);
};

which would allow you to use 't.hello' as a stand-alone thing. The value
of it would be used then. Now, how to assign that pointer a particular
value, is another question.
Or even
better.. I believe you understand what kind of use I am aiming at.. is
there a way to circumvent this problem?


See my recommendation above. The trick is still going to be the assignment
of a particular value to 'hello'.

V
Oct 28 '05 #4

P: n/a
st****@gmail.com wrote:
A pointer to a function and a pointer to a member function are not
compatible. A manipulator is expected to be a pointer to a function,
not to a member.

why is that exactly?


Because a member function has special access to one particular object. A
regular function does not. Of course there is nothing at all to stopyou
writing a regular function which calls a member function, and then you
can use the regular function where you wanted to use the member function.

john
Oct 28 '05 #5

P: n/a

Victor Bazarov wrote:
st****@gmail.com wrote:
Hello group, this is my dilemma:
------------------------------------------------------------------------

#include <iostream>

using namespace std;

// a regular manipulator
ostream & hello( ostream & os ) { return os << "regular: hello"; }

struct Test // a manipulator wrapped inside a struct
{
ostream & hello( ostream & os ) { return os << "wrapped: hello"; }


A pointer to a function and a pointer to a member function are not
compatible. A manipulator is expected to be a pointer to a function,
not to a member.
};

int main( )
{
cout << hello << endl; // this works just fine..

Test t;
cout << t.hello << endl; // and this doesn't compile! WHY??


Because 't.hello' is a syntax error. You either need 't.hello()' or
'&Test::hello', to make something of 'hello'. And the second one is not
going to fly due to pointer incompatibility I mentioned above. And the
first one is not what you want.
/* note: gcc 2.95.4 says there's no matching function to call,
* and then lists the possible applicators; but there it is:
*
* class ostream & ostream::operator <<(ostream & (*)(ostream &))
*
* isn't that the wrapped manipulator's signature?
* I don't get it. Would anyone be so kind to explain? thanks!
*/

return 0;
}


V


Vitya at his finest!!!

Do listen to Victor, I neither had seen this in production not
Victor's code. And I know Victor for quite some time now (Vitya is it
25 or 30 years in total is the duration of our acquaintance and
bestfriendship?).
Pass my birthday wishes to your sister Dinachka.

Oct 29 '05 #6

P: n/a
> Why is what exactly? I made two statements, which one are you asking about?

I meant.. why aren't a pointer to a function and a pointer to a member
function compatible?
The term is "non-static member function". Perhaps you should start using it...
Perhaps, but English is not my mother tongue so please don't take it
against me. Besides, we've understood eachother just as fine using
these different expressions. Fortunately us humans are far more
flexible than compilers :)

I've tried using the construct with ostream& (*hello)(ostream&); you
have proposed
Now, how to assign that pointer a particular value, is another question.


and this turned out to be a rather difficult question! I was unable to
get a hold of the address of my non-static member function :)

Dear Victor (and the rest of the group), I have a feeling you are
keeping some important details to yourself. My question is not an
academic one, but rather a simple design question, a question of
ergonomics if you wish. I would really appreciate your help.

Though discussing language odditys might be fun sometimes, my ultimate
goal is using the class in expressions like this:

MyClass instance;

cout << instance.something << endl;
cout << instance.somethingElse << endl;

The semantics I'm looking for is that an applicator runs 'something'
and 'somethingElse' in the context of an instance. How can I achieve
this? It doesn't have to be pretty from the inside :)

Thank you Victor, John and others..

Oct 29 '05 #7

P: n/a
st****@gmail.com wrote:
Why is what exactly? I made two statements, which one are you asking about?

I meant.. why aren't a pointer to a function and a pointer to a member
function compatible?

The term is "non-static member function". Perhaps you should start using it...

Perhaps, but English is not my mother tongue so please don't take it
against me. Besides, we've understood eachother just as fine using
these different expressions. Fortunately us humans are far more
flexible than compilers :)

I've tried using the construct with ostream& (*hello)(ostream&); you
have proposed

Now, how to assign that pointer a particular value, is another question.

and this turned out to be a rather difficult question! I was unable to
get a hold of the address of my non-static member function :)

Dear Victor (and the rest of the group), I have a feeling you are
keeping some important details to yourself. My question is not an
academic one, but rather a simple design question, a question of
ergonomics if you wish. I would really appreciate your help.

Though discussing language odditys might be fun sometimes, my ultimate
goal is using the class in expressions like this:

MyClass instance;

cout << instance.something << endl;
cout << instance.somethingElse << endl;

The semantics I'm looking for is that an applicator runs 'something'
and 'somethingElse' in the context of an instance. How can I achieve
this? It doesn't have to be pretty from the inside :)

Thank you Victor, John and others..


Well here's your problem, you want the return from instance.something()
to be a thing that remembers what instance was so that the thing can
access the context represented by instance.

Now think about what a function is, it is stateless, it cannot remember
any context or anything else. So give up on the idea of
instance.something() returning a function. Instead instance.something()
must return an object.

Something like this (untested)

class MyClass;

class MyManipulator
{
public:
MyManipulator(MyClass* i) : inst(i) {}
MyClass* get_inst() const { return inst; }
private:
MyClass* inst;
};

class MyClass
{
public:
MyManipulator something() { return MyManipulator(this); }
};

ostream& operator<<(ostream& os, const MyManipulator& m)
{
MyInstance* inst = m.get_inst();
// do something with inst
return is;
}

MyClass instance;
cout << instance.something() << endl;

john
Oct 29 '05 #8

P: n/a
Thanks John! Your suggestion pushed me into the right direction. I'll
be exploiting c++'s typesystem to overload (specialize) the
'operator<<' applicator. Basically, I've slightly modified your
solution and generalized it into a template that's simple enough to
use. I'm posting the final solution in case anyone's interested..
---------------------------------------------------------------------------------
#include <iostream>
#include <cstdlib>

using namespace std;

template<class Outer, class TypesystemHook>
class Target
{
Outer& _outer;
public:
Target( Outer& outer ) : _outer( outer ) {}
Outer& operator()( void ) { return _outer; }
};

class MyClass
{
public:

MyClass() : average(*this), sum(*this)
{
for( unsigned int i = 0; i < DataSize; i++ ) { _data[i] =
rand()%20; }
}

Target<MyClass, class Average {}> average;
friend ostream& operator<<( ostream& os, Target<MyClass,Average>& t
)
{
return os << static_cast<double>( t().getSum() ) / DataSize;
}

Target<MyClass, class Sum {}> sum;
friend ostream& operator<<( ostream& os, Target<MyClass,Sum>& t )
{
return os << t().getSum();
}

private:
static const unsigned int DataSize = 10;
int _data[DataSize];

int getSum() // helper
{
int sum = 0;
for( unsigned int i = 0; i < DataSize; i++ ) { sum += _data[i];
}
return sum;
}
};

int main( int argc, char* argv[] )
{
MyClass instance;

cout << instance.sum << endl;
cout << instance.average << endl;

return 0;
}
---------------------------------------------------------------------------------
Once again, thank you all for your helpfull suggestions and comments,
John especially!

Oct 30 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.