Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Status on references to member functions?

1 view
Skip to first unread message

Christer Palm

unread,
Jan 14, 2003, 7:00:54 PM1/14/03
to
Hi all!

Can anyone enlighten me on the status of member function references?
Does the C++ language specification allow them or not?

In particular, GCC happily compiles the following code without
warnings (and indeed does so very efficiently, which is what I'm
really after here):

class c {
private:
void a(int arg) { /* ... */ }
int b() { /* ... */ }
static int x1(int arg) { /* ... */ }

typedef int c::fcn(int);
void f(fcn& x) { a(x(b())); }

public:
void test() { f(x1); }
};

Since I have a feeling that this code is not really valid C++, I'd
also appriciate any suggestions on how to express this differently.

A bit of background:
In reality, I have quite a few xn()'s and a handful of f()'s which are
really more complex than the example, and since they're combined all
over the place I desire a shorthand notation for the combination of
f() and xn() without having to create a separate member function for
each possible combination (there are several hundreds).

I do need them to inline, and I don't want to make function objects
out of the xn()'s since they _do_ modify the state of c, and thus
belongs as member functions of c.

A few macros does, of course, work, but is obviously less than
completely elegant.

Cheers,
--
Christer Palm

Mike Wahler

unread,
Jan 14, 2003, 7:23:42 PM1/14/03
to

Christer Palm <pa...@nogui.se> wrote in message
news:71782a34.03011...@posting.google.com...

> Hi all!
>
> Can anyone enlighten me on the status of member function references?
> Does the C++ language specification allow them or not?

ISO/IEC 14882:1998(E)

8.3.3

3 A pointer to member shall not point to a static member of
a class (9.4), a member with reference type, or "cv void."
[Note: see also 5.3 and 5.5. The type "pointer to member"
is distinct from the type "pointer", that is, a pointer to
member is declared only by the pointer to member declarator
syntax, and never by the pointer declarator syntax. There
is no "referenceè² oè¡«ember" type in C++. ]


>
> In particular, GCC happily compiles the following code without
> warnings (and indeed does so very efficiently, which is what I'm
> really after here):

Must be an extension. Perhaps just put it inside an
#ifdef <whatever GCC happens to use to identify itself>

>
> class c {
> private:
> void a(int arg) { /* ... */ }
> int b() { /* ... */ }
> static int x1(int arg) { /* ... */ }
>
> typedef int c::fcn(int);
> void f(fcn& x) { a(x(b())); }
>
> public:
> void test() { f(x1); }
> };
>
> Since I have a feeling that this code is not really valid C++, I'd
> also appriciate any suggestions on how to express this differently.
>
> A bit of background:
> In reality, I have quite a few xn()'s and a handful of f()'s which are
> really more complex than the example, and since they're combined all
> over the place I desire a shorthand notation for the combination of
> f() and xn() without having to create a separate member function for
> each possible combination (there are several hundreds).
>
> I do need them to inline, and I don't want to make function objects
> out of the xn()'s since they _do_ modify the state of c, and thus
> belongs as member functions of c.
>
> A few macros does, of course, work, but is obviously less than
> completely elegant.

Why not just use pointers instead of references?

-Mike

Ioannis Vranos

unread,
Jan 14, 2003, 7:30:11 PM1/14/03
to
"Christer Palm" <pa...@nogui.se> wrote in message
news:71782a34.03011...@posting.google.com...
> Hi all!
>
> Can anyone enlighten me on the status of member function references?
> Does the C++ language specification allow them or not?

They are allowed. The only kinds of references not allowed:

"There shall be no references to references, no arrays of references, and no
pointers to references."

...

"A reference shall be initialized to refer to a valid object or function."


--
Ioannis

* Programming pages: http://www.noicys.freeurl.com
* Alternative URL: http://run.to/noicys

Ioannis Vranos

unread,
Jan 14, 2003, 7:39:33 PM1/14/03
to
"Mike Wahler" <mkwa...@mkwahler.net> wrote in message
news:b0295h$f73$1...@slb0.atl.mindspring.net...

>
> Christer Palm <pa...@nogui.se> wrote in message
> news:71782a34.03011...@posting.google.com...
> > Hi all!
> >
> > Can anyone enlighten me on the status of member function references?
> > Does the C++ language specification allow them or not?
>
> ISO/IEC 14882:1998(E)
>
> 8.3.3
>
> 3 A pointer to member shall not point to a static member of
> a class (9.4), a member with reference type, or "cv void."
> [Note: see also 5.3 and 5.5. The type "pointer to member"
> is distinct from the type "pointer", that is, a pointer to
> member is declared only by the pointer to member declarator
> syntax, and never by the pointer declarator syntax. There
> is no "referenceè² oè¡«ember" type in C++. ]


That is you can point with a reference to it directly. Consider the code:

class C
{ public:
int x;

int &s() { return x; }
};

int main()
{
C c={7};

int &x=c.x;

int &y=c.s();

}

> Must be an extension. Perhaps just put it inside an
> #ifdef <whatever GCC happens to use to identify itself>


No, i do not think so.

> Why not just use pointers instead of references?


Well he can use references.

Mike Wahler

unread,
Jan 14, 2003, 8:23:23 PM1/14/03
to
Ioannis Vranos <noi...@h01tmail.com> wrote in message
news:1042591177.654352@athprx02...

> "Mike Wahler" <mkwa...@mkwahler.net> wrote in message
> news:b0295h$f73$1...@slb0.atl.mindspring.net...
> >
> > Christer Palm <pa...@nogui.se> wrote in message
> > news:71782a34.03011...@posting.google.com...
> > > Hi all!
> > >
> > > Can anyone enlighten me on the status of member function references?
> > > Does the C++ language specification allow them or not?
> >
> > ISO/IEC 14882:1998(E)
> >
> > 8.3.3
> >
> > 3 A pointer to member shall not point to a static member of
> > a class (9.4), a member with reference type, or "cv void."
> > [Note: see also 5.3 and 5.5. The type "pointer to member"
> > is distinct from the type "pointer", that is, a pointer to
> > member is declared only by the pointer to member declarator
> > syntax, and never by the pointer declarator syntax. There
> > is no "reference­to­member" type in C++. ]

>
>
> That is you can point with a reference to it directly.


From above:

"There is no "reference­ to ­member" type in C++. "

Plain enough to me.


>Consider the code:
>
> class C
> { public:
> int x;
>
> int &s() { return x; }

This is not a reference to a member function.

It's a function which returns a reference to type int.

> };
>
>
>
> int main()
> {
> C c={7};
>
> int &x=c.x;

A reference to int, initialized with the value
of c::x. Not a reference-to-member.

>
> int &y=c.s();

A reference to int, initialized with the return value
of c::s(). Not a reference-to-member.


>
> }
>
>
>
>
>
> > Must be an extension. Perhaps just put it inside an
> > #ifdef <whatever GCC happens to use to identify itself>
>
>
> No, i do not think so.

8.3.3 / 3
"There is no "reference­ to ­member" type in C++. "

If such a beast is supported by an implementation,
it is an extension, not part of the standard language.

>
>
>
> > Why not just use pointers instead of references?
>
>
> Well he can use references.

Not to a member. It's specifically disallowed.


OP wanted to use:

typedef int c::fcn(int);
void f(fcn& x) { a(x(b())); }

The second line is invalid. (The 'fcn&' parameter)


-Mike

Mike Wahler

unread,
Jan 14, 2003, 8:24:51 PM1/14/03
to

Ioannis Vranos <noi...@h01tmail.com> wrote in message
news:1042590612.596501@athprx02...

> "Christer Palm" <pa...@nogui.se> wrote in message
> news:71782a34.03011...@posting.google.com...
> > Hi all!
> >
> > Can anyone enlighten me on the status of member function references?
> > Does the C++ language specification allow them or not?
>
> They are

not

> allowed.

See 8.3.3 / 3

> The only kinds of references not allowed:
>
> "There shall be no references to references, no arrays of references, and
no
> pointers to references."

And there is no such type as 'reference-to-member'. (8.3.3/3)

>
> ...
>
> "A reference shall be initialized to refer to a valid object or function."

Function, not member function.

-Mike

Ioannis Vranos

unread,
Jan 14, 2003, 10:06:07 PM1/14/03
to
"Mike Wahler" <mkwa...@mkwahler.net> wrote in message
news:b02cli$6hg$1...@slb6.atl.mindspring.net...

>
> From above:
>
> "There is no "reference­ to ­member" type in C++. "
>
> Plain enough to me.
>
>
> >Consider the code:
> >
> > class C
> > { public:
> > int x;
> >
> > int &s() { return x; }
>
> This is not a reference to a member function.


Yes it is a reference to a data member. And all the others.


> 8.3.3 / 3
> "There is no "reference­ to ­member" type in C++. "
>
> If such a beast is supported by an implementation,
> it is an extension, not part of the standard language.


Look i am not sure, perhaps you are right. However my feeling is that
references to member functions when used as arguments to other member
functions are allowed. It is very late here for me to think properly, but in
standard library at least references to regular functions are used heavily
(when functions are passed instead of function objects).

After i recharge i 'll deal with it. :)

Ioannis Vranos

unread,
Jan 14, 2003, 10:08:29 PM1/14/03
to
"Mike Wahler" <mkwa...@mkwahler.net> wrote in message
news:b02co8$vg8$1...@slb0.atl.mindspring.net...

>
> See 8.3.3 / 3
>
> > The only kinds of references not allowed:
> >
> > "There shall be no references to references, no arrays of references,
and
> no
> > pointers to references."
>
> And there is no such type as 'reference-to-member'. (8.3.3/3)

Members are not only the member functions but also the data members. True
there is no such notation as reference to member, however for example for
data members we can point to them with regular references. For the member
functions i shall answer tomorrow. :)

Mike Wahler

unread,
Jan 14, 2003, 11:30:01 PM1/14/03
to

Ioannis Vranos <noi...@h01tmail.com> wrote in message
news:1042599969.870025@athprx02...

> "Mike Wahler" <mkwa...@mkwahler.net> wrote in message
> news:b02cli$6hg$1...@slb6.atl.mindspring.net...
> >
> > From above:
> >
> > "There is no "reference­ to ­member" type in C++. "
> >
> > Plain enough to me.
> >
> >
> > >Consider the code:
> > >
> > > class C
> > > { public:
> > > int x;
> > >
> > > int &s() { return x; }
> >
> > This is not a reference to a member function.
>
>
> Yes it is a reference to a data member. And all the others.
>
>
> > 8.3.3 / 3
> > "There is no "reference­ to ­member" type in C++. "
> >
> > If such a beast is supported by an implementation,
> > it is an extension, not part of the standard language.
>
>
> Look i am not sure, perhaps you are right. However my feeling is that
> references to member functions when used as arguments to other member
> functions are allowed.

I did not go by feeling, but by looking it up
in the standard, which explicitly disallows
'reference-to-member.'

> It is very late here for me to think properly,

I didn't need much thinking, just reading.

>but in
> standard library at least references to regular functions are used heavily

Sure. That's valid.

> (when functions are passed instead of function objects).
>
> After i recharge i 'll deal with it. :)

:-)

-Mike

Mike Wahler

unread,
Jan 14, 2003, 11:32:35 PM1/14/03
to

Ioannis Vranos <noi...@h01tmail.com> wrote in message
news:1042600111.410595@athprx02...

> "Mike Wahler" <mkwa...@mkwahler.net> wrote in message
> news:b02co8$vg8$1...@slb0.atl.mindspring.net...
> >
> > See 8.3.3 / 3
> >
> > > The only kinds of references not allowed:
> > >
> > > "There shall be no references to references, no arrays of references,
> and
> > no
> > > pointers to references."
> >
> > And there is no such type as 'reference-to-member'. (8.3.3/3)
>
> Members are not only the member functions but also the data members.

Right. From 8.3.3 / 3

"There is no "reference­-to-­member" type in C++."

which of course includes both data members and
member functions.


> True
> there is no such notation as reference to member, however for example for
> data members we can point to them with regular references.

Right, references to whatever their type is.

>For the member
> functions i shall answer tomorrow. :)

I've already answered it several times.

-Mike

David White

unread,
Jan 15, 2003, 12:08:16 AM1/15/03
to
Ioannis Vranos <noi...@h01tmail.com> wrote in message
news:1042600111.410595@athprx02...

> Members are not only the member functions but also the data members. True
> there is no such notation as reference to member, however for example for
> data members we can point to them with regular references.

I suspect the OP wanted to know about _declaring_ something to be a
reference to a member. Declaring an ordinary reference and making it refer
to a data member does not make it a reference to a member, because the
declared reference was not confined to referring only to members.

David

Christer Palm

unread,
Jan 15, 2003, 2:27:49 AM1/15/03
to
OK - Indeed there seems to be some disagreements to whether this is
really allowed or not. Let's see how the discussion evolves...

"Mike Wahler" <mkwa...@mkwahler.net> wrote in message news:<b0295h$f73$1...@slb0.atl.mindspring.net>...


> Christer Palm <pa...@nogui.se> wrote in message
> news:71782a34.03011...@posting.google.com...
> >

> > In particular, GCC happily compiles the following code without
> > warnings (and indeed does so very efficiently, which is what I'm
> > really after here):
>
> Must be an extension.

Well, that's what I'm afraid of. OTOH, it is _not_ mentioned in the
list of extensions to the C++ language in the GCC docs
(http://gcc.gnu.org/onlinedocs/gcc-3.2.1/gcc/C---Extensions.html#C++%20Extensions).

> Perhaps just put it inside an
> #ifdef <whatever GCC happens to use to identify itself>
>

That's exactly what I intend to do (and use macros as an alternative)
if it turns out this is not valid C++.

>
> Why not just use pointers instead of references?
>

Simply because it generates extremely inefficient code (at least with
GCC) - even with declaring the argument to f() as a const pointer. I
really need this construct to inline the involved functions.

--
Christer Palm

Rob Williscroft

unread,
Jan 15, 2003, 9:01:05 AM1/15/03
to
Christer Palm wrote:
> Hi all!
>
> Can anyone enlighten me on the status of member function references?
> Does the C++ language specification allow them or not?
>
> In particular, GCC happily compiles the following code without
> warnings (and indeed does so very efficiently, which is what I'm
> really after here):
>
> class c {
> private:
> void a(int arg) { /* ... */ }
> int b() { /* ... */ }
> static int x1(int arg) { /* ... */ }
>
> typedef int c::fcn(int);

is equivelent to
typedef int fcn(int);


> void f(fcn& x) { a(x(b())); }

is equivelent to

void f(void (&fcn)(int) x) { a(x(b())); }

is equivelent to

void c::f(void (&fcn)(int) x) { a(x(b())); }

Note sticking 'c::' in there doesn't make any difference it's just
redundant scope resolution.

>
> public:
> void test() { f(x1); }
> };
>
> Since I have a feeling that this code is not really valid C++, I'd
> also appriciate any suggestions on how to express this differently.

It is valid C++, it just isn't doing what you (seem) think it's doing.

>
> A bit of background:
> In reality, I have quite a few xn()'s and a handful of f()'s which are
> really more complex than the example, and since they're combined all
> over the place I desire a shorthand notation for the combination of
> f() and xn() without having to create a separate member function for
> each possible combination (there are several hundreds).
>
> I do need them to inline, and I don't want to make function objects

Any inlining your getting can only be because GCC has a good
(global) optimizer, once you start having lots of f()'s & xn()'s
It'll probably stop inlining.

> out of the xn()'s since they _do_ modify the state of c, and thus
> belongs as member functions of c.
>

The only way's to pass a function that you want to be inlined
around are functors and macros, as soon as you make it a
pointer (or refrence) its unlikely to be inlined.

Rob.

Ioannis Vranos

unread,
Jan 15, 2003, 9:33:40 AM1/15/03
to
"David White" <n...@email.provided> wrote in message
news:3Z5V9.489$3x1....@nasal.pacific.net.au...


Yes but you can still do:

class A
{
int x;
int &y;

public:
A(int r):x(r), y(x) {}
};

Ioannis Vranos

unread,
Jan 15, 2003, 9:35:39 AM1/15/03
to
"Rob Williscroft" <r...@REMOVE-freenet.co.uk> wrote in message
news:3E2569A1...@REMOVE-freenet.co.uk...

> > typedef int c::fcn(int);
>
> is equivelent to
> typedef int fcn(int);
>
>
> > void f(fcn& x) { a(x(b())); }
>
> is equivelent to
>
> void f(void (&fcn)(int) x) { a(x(b())); }
>
> is equivelent to
>
> void c::f(void (&fcn)(int) x) { a(x(b())); }
>
> Note sticking 'c::' in there doesn't make any difference it's just
> redundant scope resolution.
>
> It is valid C++, it just isn't doing what you (seem) think it's doing.
>
> Any inlining your getting can only be because GCC has a good
> (global) optimizer, once you start having lots of f()'s & xn()'s
> It'll probably stop inlining.
>
> > out of the xn()'s since they _do_ modify the state of c, and thus
> > belongs as member functions of c.
> >
>
> The only way's to pass a function that you want to be inlined
> around are functors and macros, as soon as you make it a
> pointer (or refrence) its unlikely to be inlined.


Yes exactly (and i am 110% recharged).

Ioannis Vranos

unread,
Jan 15, 2003, 9:46:09 AM1/15/03
to
> "Rob Williscroft" <r...@REMOVE-freenet.co.uk> wrote in message
> news:3E2569A1...@REMOVE-freenet.co.uk...
>
> > The only way's to pass a function that you want to be inlined
> > around are functors and macros, as soon as you make it a
> > pointer (or refrence) its unlikely to be inlined.


By functiors you probably mean function objects. Also better avoid macros.
Also using template classes with inline static functions is good for
inlining. For example:


class something
{
public:
static void f()
{
// ...
}

// ...
};


template <class T>
void g()
{
T::f();
}

Functions passed in this way can be easily inlined and also this method has
more efficiency gains. When you want to pass many functions with this way
they are passed faster.

Ioannis Vranos

unread,
Jan 15, 2003, 9:48:18 AM1/15/03
to
"Ioannis Vranos" <noi...@h01tmail.com> wrote in message
news:1042641969.501508@athprx02...
>
> Also using template classes with inline static functions...

Also using classes with inline static functions passed to template
functions...

Rob Williscroft

unread,
Jan 15, 2003, 10:21:02 AM1/15/03
to
Ioannis Vranos wrote:
>>"Rob Williscroft" <r...@REMOVE-freenet.co.uk> wrote in message
>>news:3E2569A1...@REMOVE-freenet.co.uk...
>>
>>
>>>The only way's to pass a function that you want to be inlined
>>>around are functors and macros, as soon as you make it a
>>>pointer (or refrence) its unlikely to be inlined.
>>
>
>
> By functiors you probably mean function objects. Also better avoid macros.


struct functor
{
some_type operator() (/* some arglist */)
{
// inline definition.
}
};


template <typename T>
void g(T const &func)
{
func( /*...*/ );
}

inline int normal(/* some arglist */)
{

}

int main()
{
g(functor()); // tempory binds to const.

/* pass a reference to an out of line version of normal()
*/
g(normal);
}


The way you do it bellow is probably better for the OP
as there's no need to create a tempory 1 byte/no constuctor
functor object.


> Also using template classes with inline static functions is good for
> inlining. For example:
>
>
> class something
> {
> public:
> static void f()
> {
> // ...
> }
>
> // ...
> };
>
>
> template <class T>
> void g()
> {
> T::f();
> }
>
>
>
> Functions passed in this way can be easily inlined and also this method has
> more efficiency gains. When you want to pass many functions with this way
> they are passed faster.
>

Rob.


Christer Palm

unread,
Jan 15, 2003, 5:45:50 PM1/15/03
to
Hi!

Rob Williscroft <r...@REMOVE-freenet.co.uk> wrote in message news:<3E2569A1...@REMOVE-freenet.co.uk>...

> Christer Palm wrote:
> >
> > typedef int c::fcn(int);
>
> is equivelent to
> typedef int fcn(int);
>

Yes, that seems to be correct. I.e the 'c::' doesnt restrict fcn to
members of c.

I also realize now that it doesn't work unless I declare the x1()
static, which, except for scope, makes it more or less equvivalent to
a non-member function.

So what we really have here is a "reference to function" I guess?

> void f(void (&fcn)(int) x) { a(x(b())); }

> void c::f(void (&fcn)(int) x) { a(x(b())); }
>

I get your point, but I assume you mean 'void f(int (&x)(int))'?

> Any inlining your getting can only be because GCC has a good
> (global) optimizer, once you start having lots of f()'s & xn()'s
> It'll probably stop inlining.
>

I tried it, and indeed GCC stops inlining the xn()'s after having put
the ~30 first inline. :-(

> The only way's to pass a function that you want to be inlined
> around are functors and macros, as soon as you make it a
> pointer (or refrence) its unlikely to be inlined.

:-(

Yeah, I guess that was basically my conclusion too, I was just hoping
that I was wrong.

The problem with functors is that they would not belong to c, which
means that I have to explicitly pass 'this' along to the functor. Not
very nice.

Additionally, the verbosity of functor vs. member function declaration
would seriously bloat the code in this case. We're talking about ~100
3-liners.

So guess I will have to bite the dust and go with the macros.

Ioannis Vranos

unread,
Jan 15, 2003, 7:12:44 PM1/15/03
to
"Christer Palm" <pa...@nogui.se> wrote in message
news:71782a34.03011...@posting.google.com...
>
> So guess I will have to bite the dust and go with the macros.


Why use macros? As a rule of thumb in C++ you should use templates or inline
functions in place of macros.

Ioannis Vranos

unread,
Jan 15, 2003, 7:10:36 PM1/15/03
to
"Christer Palm" <pa...@nogui.se> wrote in message
news:71782a34.03011...@posting.google.com...
>
> So guess I will have to bite the dust and go with the macros.

Avoid macros!

Christer Palm

unread,
Jan 16, 2003, 4:39:28 PM1/16/03
to
Hello Ioannis!

"Ioannis Vranos" <noi...@h01tmail.com> wrote in message news:<1042675964.40547@athprx02>...


> "Christer Palm" <pa...@nogui.se> wrote in message
> news:71782a34.03011...@posting.google.com...
> >
> > So guess I will have to bite the dust and go with the macros.
>
>
> Why use macros? As a rule of thumb in C++ you should use templates or inline
> functions in place of macros.

OK, so perhaps I'm still missing something here...

How can I use inline functions or templates to replace macros for this
particular problem?

Regards,
--
Christer Palm

Ioannis Vranos

unread,
Jan 16, 2003, 6:15:03 PM1/16/03
to
"Christer Palm" <pa...@nogui.se> wrote in message
news:71782a34.03011...@posting.google.com...
>
> OK, so perhaps I'm still missing something here...
>
> How can I use inline functions or templates to replace macros for this
> particular problem?


So if i understand well your problem is that you wish to avoid the time cost
of function calls of a static function, that is the function to be inlined.


Well you can do directly in that definition of yours:

class c {
private:
void a(int arg) { /* ... */ }
int b() { /* ... */ }

==> inline static int x1(int arg) { /* ... */ }

typedef int fcn(int);
void f(fcn& x) { a(x(b())); }

public:
void test() { f(x1); }
};

To push things further:

class c {
private:
void a(int arg) { /* ... */ }
int b() { /* ... */ }

==> inline static int x1(int arg) { /* ... */}

==> template<class T>
inline void f(T &x) { a(x(b())); }

public:
void test() { f(x1); }
};


You can push things even further.

Christer Palm

unread,
Jan 17, 2003, 1:55:24 AM1/17/03
to
Hi!

"Ioannis Vranos" <noi...@h01tmail.com> wrote in message news:<1042758902.529733@athprx02>...


>
> To push things further:
>
> class c {
> private:
> void a(int arg) { /* ... */ }
> int b() { /* ... */ }
> ==> inline static int x1(int arg) { /* ... */}
>
> ==> template<class T>
> inline void f(T &x) { a(x(b())); }
>
> public:
> void test() { f(x1); }
> };
>

OK - that is just as the solution I suggested myself in my initial post.

As stated earlier, the problem is that;
1) I don't want x1 to be static.
2) GCC stops inlining xN() after ~30 calls to f().

Regards,
--
Christer Palm

Ioannis Vranos

unread,
Jan 17, 2003, 11:23:35 AM1/17/03
to
"Christer Palm" <pa...@nogui.se> wrote in message
news:71782a34.03011...@posting.google.com...


Ok then don't make x1 static. Now i wonder what is the problem in reality.
Since everything is defined inside the class why do you want to pass x1 as
an argument?!

Christer Palm

unread,
Jan 18, 2003, 7:05:55 AM1/18/03
to
"Ioannis Vranos" <noi...@h01tmail.com> wrote in message news:<1042820612.375463@athprx02>...

>
> Ok then don't make x1 static.

If I do not make x1 static, the code does not compile.

> Now i wonder what is the problem in reality.
> Since everything is defined inside the class why do you want to pass x1 as
> an argument?!

Because it seems that I cannot pass a member function as an argument
without using a member function pointer! GCC (and probably most other
compilers) generates inefficient code if I use function pointers -
hence it seems that I need to use macros instead.

--
Christer Palm

Ioannis Vranos

unread,
Jan 18, 2003, 11:46:20 AM1/18/03
to
"Christer Palm" <pa...@nogui.se> wrote in message
news:71782a34.03011...@posting.google.com...
> "Ioannis Vranos" <noi...@h01tmail.com> wrote in message
news:<1042820612.375463@athprx02>...
> >
> > Ok then don't make x1 static.
>
> If I do not make x1 static, the code does not compile.

? Can you give me a working example what do you mean by that with a main()?


>
> > Now i wonder what is the problem in reality.
> > Since everything is defined inside the class why do you want to pass x1
as
> > an argument?!
>
> Because it seems that I cannot pass a member function as an argument
> without using a member function pointer! GCC (and probably most other
> compilers) generates inefficient code if I use function pointers -
> hence it seems that I need to use macros instead.


Why should you pass a member function as an argument? I think you have a
great misconception here. Here is an example:

class c {
private:
void a(int arg) { /* ... */ }
int b() { /* ... */ }

int x1(int arg) { /* ... */ }

void f() { a(x1(b())); }

public:
void test() { f(); }
};

Christer Palm

unread,
Jan 18, 2003, 5:25:19 PM1/18/03
to
After spending some more time thinking about this problem, it appears
that using "adapter function objects" provides a somewhat reasonable
solution:

class c {
private:
void a(int arg) { /* ... */ }
int b() { /* ... */ }

int x1(int arg) { /* ... */ }

struct {
int operator()(c& cref, int arg)
{ return cref.x1(arg); }
} x1_adapter;

template<class Adapter> void f(Adapter& fcn)
{ a(fcn(*this,b())); }

public:
void test() { f(x1_adapter); }
};

The complication beeing, of course, that I have to add ~200 lines of
code for the adapter definitions - but at least this technique allows
me to keep that bloat separate from the xN() implementations.

Any comments?

--
Christer Palm

Rob Williscroft

unread,
Jan 18, 2003, 6:09:16 PM1/18/03
to

I tried this

#include <iostream>

struct C_test
{
int b() { return 2; }
int x1(int n) { return n + 2; }

static int s_x1(C_test *that, int n) { return that->x1(n); }

template <int F(C_test *, int)>
void f() { std::cout << "\nC_test " << F(this, b()) << "\n"; }
};


int main()
{
C_test ct;

ct.f<C_test::s_x1>();
}

The output of g++ -O3 -S appeared to be inlined except for the
cout << calls. You'll need to check if it scales up though.

Alternatively you could change your class above:


struct x1_adapter
{
static int call(c& cref, int arg)
{
return cref.x1(arg);
}
);

template<class Adapter> void f()
{
a(Adapter::call(*this,b()));
}

void test() { f<x1_addapter>(); }


Rob.

Christer Palm

unread,
Jan 18, 2003, 6:58:26 PM1/18/03
to
"Ioannis Vranos" <noi...@h01tmail.com> wrote in message news:<1042908382.649310@athprx02>...

>
> Why should you pass a member function as an argument? I think you have a
> great misconception here. Here is an example:
>

Duh...

Stop trolling, or learn how to read and understand the question before
posting an answer, whichever is applicable.

--
Christer Palm

Ioannis Vranos

unread,
Jan 18, 2003, 9:25:24 PM1/18/03
to
"Christer Palm" <pa...@nogui.se> wrote in message
news:71782a34.03011...@posting.google.com...
>
> Duh...
>
> Stop trolling, or learn how to read and understand the question before
> posting an answer, whichever is applicable.


The answer to the original question is that references to member functions
passed to other member functions are allowed. However all member function
names have scope inside the whole class regardless the orfer of
definition/declaration, so passing them to one another is of no use.

Christer Palm

unread,
Jan 18, 2003, 10:27:02 PM1/18/03
to
Rob Williscroft <r...@REMOVE-freenet.co.uk> wrote in message news:<3E29DE9C...@REMOVE-freenet.co.uk>...

>
> struct C_test
> {
> int b() { return 2; }
> int x1(int n) { return n + 2; }
>
> static int s_x1(C_test *that, int n) { return that->x1(n); }
>
> template <int F(C_test *, int)>
> void f() { std::cout << "\nC_test " << F(this, b()) << "\n"; }
> };
>
>

Elaborating a bit further on that, I came up with the following
snippet which I think quite clearly demonstrates why the lack of a
"reference to member function" type in C++ seems to be quite stupid:

class c {
private:
void x1() { }
static void x1_s(c& cref) { cref.x1(); }

template <typename T> void f_s(T& x) { x(*this); }
template <typename T> void f(T& x) { x(); }

public:
// OK - calling x1() through static "gateway"
void test_s() { f_s(x1_s); }

// Wrong! Can't make reference to member function
void test() { f(x1);}
};

Can anyone explain the reason to this lack of orthogonality?
To me, this seems like a rather trivial oversight...

--
Christer Palm

Ioannis Vranos

unread,
Jan 19, 2003, 12:54:41 AM1/19/03
to
"Christer Palm" <pa...@nogui.se> wrote in message
news:71782a34.03011...@posting.google.com...
>
> class c {
> private:
> void x1() { }
> static void x1_s(c& cref) { cref.x1(); }
>
> template <typename T> void f_s(T& x) { x(*this); }
> template <typename T> void f(T& x) { x(); }
>
> public:
> // OK - calling x1() through static "gateway"
> void test_s() { f_s(x1_s); }
>
> // Wrong! Can't make reference to member function
> void test() { f(x1);}
> };
>
> Can anyone explain the reason to this lack of orthogonality?
> To me, this seems like a rather trivial oversight...

f<something>(x1);

You do not provide a type.

Ioannis Vranos

unread,
Jan 19, 2003, 1:15:03 AM1/19/03
to
"Ioannis Vranos" <noi...@h01tmail.com> wrote in message
news:1042955683.401698@athprx02...

> "Christer Palm" <pa...@nogui.se> wrote in message
>
> f<something>(x1);
>
> You do not provide a type.


My mistake. I 'll think about it later (unless someone else finds the
cause).

Rob Williscroft

unread,
Jan 19, 2003, 8:01:15 AM1/19/03
to
Christer Palm wrote:
> Elaborating a bit further on that, I came up with the following
> snippet which I think quite clearly demonstrates why the lack of a
> "reference to member function" type in C++ seems to be quite stupid:
>
> class c {
> private:
> void x1() { }
> static void x1_s(c& cref) { cref.x1(); }
>
> template <typename T> void f_s(T& x) { x(*this); }
> template <typename T> void f(T& x) { x(); }
>
> public:
> // OK - calling x1() through static "gateway"
> void test_s() { f_s(x1_s); }
>
> // Wrong! Can't make reference to member function
> void test() { f(x1);}
> };
>
> Can anyone explain the reason to this lack of orthogonality?
> To me, this seems like a rather trivial oversight...


class c {
private:
void x1() { }
static void x1_s(c& cref) { cref.x1(); }

template <typename T> void f_s(T const & x) { x(*this); }
template <typename T> void f(T const & x) { (this->*x)(); }

public:
// OK - calling x1() through static "gateway"
void test_s() { f_s(x1_s); }

// Wrong! Can't make reference to member function

void test() { f(&c::x1);}
};

Both of your templates take a pointer. You took a reference to it
and I took a constant reference to it but it's still a pointer.

In f_s() the argument is a function pointer, and in test_s() the
argument x1_s can be implicitly converted.
In f() the argument is going to be a pointer to member function,
and in test() the argument can't be implicitly converted, so you
have to write &c::x1.

Why this is so? I suspect the first case is just the way it was
done in the existing C language. But maybe there's a technical
reason, though I can't think of any.

The other point is you can call a function pointer, say void (*fp)(),
like fp() rather than the more verbose (*fp)(). With a member pointer,
say void (c::*pmf)(), you have to call it like (this->*pmf)().
I guess if C++ were to allow pmf to be implicitly converted it
should also allow it to be implicitly called, but only in a
member function.


Rob.

Christer Palm

unread,
Jan 19, 2003, 3:29:09 PM1/19/03
to
Rob Williscroft <r...@REMOVE-freenet.co.uk> wrote in message news:<3E2AA19B...@REMOVE-freenet.co.uk>...

>
> Both of your templates take a pointer. You took a reference to it
> and I took a constant reference to it but it's still a pointer.
>
> In f_s() the argument is a function pointer, and in test_s() the
> argument x1_s can be implicitly converted.
> In f() the argument is going to be a pointer to member function,
> and in test() the argument can't be implicitly converted, so you
> have to write &c::x1.
>

OK, I get your point, and it is indeed interesting.

However, consider the following code:

void x1() { }
template<typename T> void f1(T x) { cout << typeid(x).name() << endl;
}
template<typename T> void f2(T& x) { cout << typeid(x).name() << endl;
}

int main()
{
f1(x1); // Implicit function pointer - x is PFv_v
f1(&x1); // Explicit function pointer - x is still PFv_v
f2(x1); // Implicit function _reference_ - x is now Fv_v
}

Indeed, passing x1 to f1() causes an implicit conversion to a function
pointer.

But in the case of f2() which explicitly takes a reference argument,
x1 seems to be passed as a reference to function, and not a reference
to a function pointer.

This makes perfect sense, because you cannot have a reference to a
non-variable.
I.e. you cannot do:

int a;
f2(&a); // Error: could not convert `&a' to `int *&'

While this is fine:

int a;
int *p = &a;
f2(p); // OK - x is now Pi

Thus;

f2(&x1);

does not even compile.

So, the bottom line is that I still argue that the code in my previous
post demonstrates the use of a "reference to function" and that there
are no function pointers involved - explicitly or implicitly.

The "reference to function type" is obviously a construct unique to
C++ (in the sense that it does not have a C counterpart). The lack of
this concept for member functions seems strange, because you can have
a pointer to either type.

Do I make sense?

--
Christer Palm

Rob Williscroft

unread,
Jan 20, 2003, 11:19:47 AM1/20/03
to
Christer Palm wrote:
> Rob Williscroft <r...@REMOVE-freenet.co.uk> wrote in message news:<3E2AA19B...@REMOVE-freenet.co.uk>...
>
>>Both of your templates take a pointer. You took a reference to it
>>and I took a constant reference to it but it's still a pointer.
>>
>>In f_s() the argument is a function pointer, and in test_s() the
>>argument x1_s can be implicitly converted.
>>In f() the argument is going to be a pointer to member function,
>>and in test() the argument can't be implicitly converted, so you
>>have to write &c::x1.
>>
>
>
> OK, I get your point, and it is indeed interesting.
>
> However, consider the following code:
>
> void x1() { }
> template<typename T> void f1(T x) { cout << typeid(x).name() << endl;
> }
> template<typename T> void f2(T& x) { cout << typeid(x).name() << endl;
> }
>
> int main()
> {
> f1(x1); // Implicit function pointer - x is PFv_v
> f1(&x1); // Explicit function pointer - x is still PFv_v
> f2(x1); // Implicit function _reference_ - x is now Fv_v
> }
>
> Indeed, passing x1 to f1() causes an implicit conversion to a function
> pointer.

Agreed - I was wrong in describing f_s() as taking a function pointer,
you can write function's like this:
void function(void (&f)()) { f(); }
but to be clear the differences from void function(void (*f)()) is
that in function you cant write (*f)() or f = new_value.

>
> But in the case of f2() which explicitly takes a reference argument,
> x1 seems to be passed as a reference to function, and not a reference
> to a function pointer.
>
> This makes perfect sense, because you cannot have a reference to a
> non-variable.
> I.e. you cannot do:
>
> int a;
> f2(&a); // Error: could not convert `&a' to `int *&'
>
> While this is fine:
>
> int a;
> int *p = &a;
> f2(p); // OK - x is now Pi
>
> Thus;
>
> f2(&x1);
>
> does not even compile.
>
> So, the bottom line is that I still argue that the code in my previous
> post demonstrates the use of a "reference to function" and that there
> are no function pointers involved - explicitly or implicitly.

It does.

>
> The "reference to function type" is obviously a construct unique to
> C++ (in the sense that it does not have a C counterpart). The lack of
> this concept for member functions seems strange, because you can have
> a pointer to either type.
>
> Do I make sense?
>

Yes, but you could also ask another question, why are references to
functions part of C++ since they don't provide any utility that
isn't provided by function pointers. I think the answer is that
it allows a simple function to behave like a 'functor', particularly
a 'reference to a functor', more efficiently. This is important for
the standard library algorithms.

The other question is why are the .* and ->* part of C++, sure you
could argue that function pointers have an equivalent in the (*f)()
syntax, but I have at least one compiler that gives me a diagnostic
telling me its unnecessary if I use it.

<fantasy-C++>
class base
{
void p();
};
class derived: public base
{
void p();
void f(void (base::&p)())
{
p();
this->p();
this->base::p();
this->derived::p();
}
};
class not_derived
{
void f(void (base::&p)())
{
p(); // an error I would hope.
derived *d = whatever;
d->p();
}
};
</fantasy-C++>

Even though I wrote the above in my own fantasy dialect of C++,
the only line were I know whats going on is the error!

If the above code were to be allowed the language would become
far more complecated, paricularly the . and -> operators.

I can't see any real advantage over just using .* and ->*.

Rob.

Christer Palm

unread,
Jan 21, 2003, 12:28:55 PM1/21/03
to
Rob Williscroft wrote:

> Christer Palm wrote:
> >
> > The "reference to function type" is obviously a construct unique to
> > C++ (in the sense that it does not have a C counterpart). The lack of
> > this concept for member functions seems strange, because you can have
> > a pointer to either type.
> >
> > Do I make sense?
> >
>
> Yes, but you could also ask another question, why are references to
> functions part of C++ since they don't provide any utility that
> isn't provided by function pointers. I think the answer is that
> it allows a simple function to behave like a 'functor', particularly
> a 'reference to a functor', more efficiently. This is important for
> the standard library algorithms.
>

> The other question is why are the .* and ->* part of C++

Yeah, I guess all this just leads us up to the conclusion that you
reach far too often when exploring these aspects of C++. The C++
language does not itself embrace, but rather emulates many of the
concepts and principles associated with object oriented programming
which results in a lot of annoying irregularities.

The first question you bring up is a perfect example. In C++, a
function looks like an object. You can also have an object that looks
like a function (i.e. a 'functor'). Yet, in C++, a function _is_ not
an object.


In fact, you could ask yourself why the following statements aren't
true:

- Built-in types are classes. Class == type.

- Consequently, "int f() { ... }" is shorthand notation of "class {
int operator()() { ... } f;". I.e. functions are objects.

- The built-in type "void" is contentless, and as such cannot be
instantiated.

- void is the implicit ancestor of all classes, i.e:
int a;
void* p = &a; // Fine, int is superclass of void
int* pi = p; // Error, void is not an int

- There's an implicit class "main" surrounding your program. All
"global" objects are actually members of this implicit class. The
"main" class is implicitly instantiated when the program runs. main()
is the constructor of this class.

--
Christer Palm

0 new messages