473,395 Members | 1,791 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

a manipulator wrapped inside a struct/class does not compile

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
8 1772
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
> 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
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
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

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
> 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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: rwawryk | last post by:
Hi, Does anybody know how to implement parametrized stream operator (such as setw, setfill)? I need to put into the stream variable of type char* without terminating NULL. It would be great if I...
8
by: Boris | last post by:
Is it possible to manipulate the std::ostream to prepend a string when performing output, e.g. // manipute std::cout to prepend "prefix " std::cout << "hallo" << std::endl; // results in...
1
by: Bob Rock | last post by:
Hello, in the last few days I've made my first few attempts at creating mixed C++ managed-unmanaged assemblies and looking aftwerwards with ILDASM at what is visible in those assemblies from a...
1
by: Bryan Parkoff | last post by:
I know how to write "Pointer to Function" inside struct or class without using static, but I have decided to add static to all functions inside struct or class because I want member functions to be...
19
by: Geetesh | last post by:
Recently i saw a code in which there was a structer defination similar as bellow: struct foo { int dummy1; int dummy2; int last }; In application the above array is always allocated at...
6
by: jack | last post by:
I have a class which overloads the insertion operator '<<' for every type that ostream handles. I do this so that I can use my class a direct replacement for cout and cerr where the insertion...
6
by: Roman | last post by:
Hi, Does anyone know why in C++, it is ok to initialize a const static int inside a class, but you can't initialize a float? From what I understand, initialization of const static float can...
5
by: huili80 | last post by:
For example, like in the following, the part commented out was intended as partial spectialzation, but it would even compile. Is it even legal to partially specialize a nested template class...
8
by: Jonathan Sachs | last post by:
I'm trying to compose a list of items, each of which consists of text that wraps around a picture at the left margin. The examples I have seen tell me to do it like this: <p><img src="xxxx.jpg"...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.