Topic: Initializing Function References


Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Wed, 27 Jun 2001 20:21:39 GMT
Raw View
In article <d18_6.253368$p33.5079040@news1.sttls1.wa.home.com>, Paul
Mensonides <pmenso57@home.com> writes
>Basically, I'm wondering if function references are special cases in the
>standard.

It may just cast light on my ignorance, but I have never come across a
function reference, and have no idea as to how I would write one. I am
also uncertain that being able to do so would buy me anything useful.
The reason for using function pointers is that they can be assigned to,
thereby changing the function called by their being used, but why would
I want a function reference (all the desirable functionality is provided
via function pointers) and if I had one, what would I do with it?

I think the reason that you got no answers on c.l.c++.m was exactly
because no one had anything to say on the subject. BTW, IIRC, functions
are always function pointers (i.e. it is their address that counts) and
all the parenthetical arguments provide is the data to be evaluated and
stored prior to 'jumping' to that address.




Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Bill Wade <wrwade@swbell.net>
Date: Thu, 28 Jun 2001 09:46:02 GMT
Raw View
"Francis Glassborow" <francis.glassborow@ntlworld.com> wrote

> ... I am
> also uncertain that being able to [write a function reference] would buy
me
> anything useful [compared to a function pointer].

If someone were to say "I am uncertain that using an int& is ever better
than using an int*" he might be told:

  1) The int& has some notational convenience compared to the int*.
  2) With int& the "pointer" is pretty much fixed.  Note that this is
approximately the same as int*const.
  3) Compared to int*, very rarely will you come across an uninitialized
int&.  Note that this is approximately the same as int*const.
  4) Compared to int*, very rarely will you come across a NULL int&.
  5) By convention, it is much less likely that you are supposed to delete
(or free() or delete[], ...) the "pointer" associated with int&.

I can't convince myself that (1) or (5) are effective arguments for function
references.  However I do believe that (2), (3), and (4) remain just as
strong for any reference type, including function references.

On the other hand, function references are a relatively obscure feature,
I've heard rumors that in some development environments programmers are
actually encouraged to write code that is readable by humans. YMMV.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Paul Mensonides" <pmenso57@home.com>
Date: Thu, 28 Jun 2001 15:04:49 GMT
Raw View
Thanks, Andrei.  I knew VC++ was screwing up somewhere (by either allowing it or
generating bad code).

Paul Mensonides

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Paul Mensonides" <pmenso57@home.com>
Date: Thu, 28 Jun 2001 15:05:03 GMT
Raw View
"Francis Glassborow" <francis.glassborow@ntlworld.com> wrote in message
news:2KG4uWAmqZO7Ewyf@ntlworld.com...
> It may just cast light on my ignorance, but I have never come across a
> function reference, and have no idea as to how I would write one. I am
> also uncertain that being able to do so would buy me anything useful.
> The reason for using function pointers is that they can be assigned to,
> thereby changing the function called by their being used, but why would
> I want a function reference (all the desirable functionality is provided
> via function pointers) and if I had one, what would I do with it?

A function reference has the same rules as a regular reference.  For example, it
cannot be null.  One of the more useful things that it could be useful for is
guaranting that an argument must not be null, and guaranting that a return value
is not null.  i.e.

void f() {
    // ...
}

void g() {
    // ...
}

typedef void (& reftype)(void);

reftype get(int x) { // or:  void (& get(int x))(void);
    if (x > 0) return f;
    return g;
}

void call(reftype rf) { // or:  void call(void (& reftype)(void));
    rf(); // no check for null:  reference is guaranteed
    return;
}

int main(void) {
    get(0)(); // no check for null:  reference is guaranteed
    call(f);
    return 0;
}


> I think the reason that you got no answers on c.l.c++.m was exactly
> because no one had anything to say on the subject. BTW, IIRC, functions
> are always function pointers (i.e. it is their address that counts) and
> all the parenthetical arguments provide is the data to be evaluated and
> stored prior to 'jumping' to that address.

Obviously, but they can be initialized in parameter in a *safe* way, unlike
function pointers which can be null and can be assigned to.  By the way (with
the function type above):

typedef void (ftype)(void); // ftype = function type

ftype f; // predeclaration of f() from above

typedef void (*fptr)(void); // fptr = pointer to function
typedef void (&fref)(void); // fref = reference to function

For the last two typedefs, you could have done this:

typedef ftype* fptr;
typedef ftype& fref;

The really annoying thing is that you can't have references to member functions:

typedef void (X::& illegal)(void);

The biggest reason that I asked about this (i.e. what I want to use it for) was
because of an argument I was having on this newsgroup about overloading by
return type and how ugly explicit resolution would get:

short g(short a);
char g(char a);

int main(void) {
    int y = 0;
    int x = static_cast<char>(g)(static_cast<char>(y));
        // or:  static_cast<char>(g(static_cast<char>(y)));
    return 0;
}

So I made a "cast-like" template function to resolve any function call that
wasn't exactly the same (parameters and return type), but I wanted the
...._cast<char>(g)(...) syntax rather than ..._cast<char>(g(...)) syntax so I
need to return a functor, but I wanted to see if I could get the functor object
itself optimized away, and I figured it might do better with references.  So,
given this example:

#include "ambiguous.h"

namespace A {
    int f();
    int g(int x, double y);
    int g(int x, int y);
}

namespace B {
    double f();
    double g(int x, int y);
}

namespace C {
    using A::f;
    using B::f;
}

int main() {
    int x = ambiguity_cast<int>(C::f)(); // A::f
    double y = ambiguity_cast<double, int, int>(C::g)(0, 0);  // B::g
    x = ambiguity_cast<int, int, double>(C::g)(0, 0.0); // A::g (#1)
    return 0;
}

Everything works fine if I use a function pointer inside the functor
implementation and actually pass a function name (rather than an actual
reference to a function) to ambiguity_cast.  VC++ chokes on initializing a
function reference with another function reference however, so maybe I should
just use pointers.  I can still get the syntax I wanted.  With this, you can
explicitly resolve any function call (I implemented it up to ten arguments) that
is normally a pain when they get brought into the same scope somehow.

Paul Mensonides

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
Date: Thu, 28 Jun 2001 17:47:16 GMT
Raw View
Francis Glassborow <francis.glassborow@ntlworld.com> writes:

| In article <d18_6.253368$p33.5079040@news1.sttls1.wa.home.com>, Paul
| Mensonides <pmenso57@home.com> writes
| >Basically, I'm wondering if function references are special cases in the
| >standard.
|
| It may just cast light on my ignorance, but I have never come across a
| function reference, and have no idea as to how I would write one. I am
| also uncertain that being able to do so would buy me anything useful.

Function references provide the same flexibility as namespace aliases
do, that is renaming. Since references are not rebindable, an
implementation can take advantage of that fact and replace use of a
function reference with the actual function (thus inlining if
possible) pretty much the same way it does with const objects
denotiing numerical values -- such an optimization can be done with
function pointers but that demands more sophisticated infrastructure.

--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Paul Mensonides" <pmenso57@home.com>
Date: Tue, 26 Jun 2001 23:00:56 GMT
Raw View
I have several questions that I asked at comp.lang.c++ but it seems nobody was
interested...

Firstly, is it legal to dereference a function pointer to initialize a function
reference?

typedef void (ftype)();

ftype f;

int main() {
    ftype* pf = &f;
    ftype& rf = *pf; // is this legal?
    return 0;
}

Secondly, is it legal to initialize a function reference with another function
reference?

#include <above_stuff>

int main() {
    ftype& rf = f;
    ftype& rf2 = rf;
    return 0;
}

If not, why not?

It seems to me that this second one, at least, should be legal.  The only reason
that I ask is that VC++ compiles the second one just fine, but the program
crashes every time it tries to call through said reference.

Thirdly, is it legal to obtain the address of a function by applying the
address-of operator to a function reference?

#include <above_stuff>

int main() {
    ftype& rf = f;
    ftype* pf = &f; // VC++ compile time error
    return 0;
}

VC++ won't compile this at all, but it seems to me that the operator should work
with regards to what is being referenced rather than the reference itself.

Basically, I'm wondering if function references are special cases in the
standard.

Paul Mensonides


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: iltchenko@yahoo.com (Andrei Iltchenko)
Date: Wed, 27 Jun 2001 16:36:45 GMT
Raw View
"Paul Mensonides" <pmenso57@home.com> wrote in message news:<d18_6.253368$p33.5079040@news1.sttls1.wa.home.com>...

> I have several questions that I asked at comp.lang.c++ but it seems nobody was
> interested...
>
> Firstly, is it legal to dereference a function pointer to initialize a function
> reference?
>
> typedef void (ftype)();
>
> ftype f;
>
> int main() {
>     ftype* pf = &f;
>     ftype& rf = *pf; // is this legal?
>     return 0;
> }

Yeah, the above is absolutely legal. Subject, of course, to you
providing a definition for the function 'f' somewhere in the same
program. The reason why it's legal is that the expression '*pf' is an
lvalue, which makes it possible for the reference binding 'ftype& rf =
*pf;'.


> Secondly, is it legal to initialize a function reference with another function
> reference?
>
> #include <above_stuff>
>
> int main() {
>     ftype& rf = f;
>     ftype& rf2 = rf;
>     return 0;
> }

That's pefectly alright too, as the sub-expression 'rf' is again an
lvalue referring to a function.


> It seems to me that this second one, at least, should be legal.  The only reason
> that I ask is that VC++ compiles the second one just fine, but the program
> crashes every time it tries to call through said reference.

I checked the assembly code that VC++ 6.0 generates in this case, and
yes, you are right, VC is at fault there. With optimizations on it
chose not to allocate any storage for both the references (which is
OK), but it incorrectly resolves the reference 'rf2'. On a conforming
implementation your test case will work as expected.


> Thirdly, is it legal to obtain the address of a function by applying the
> address-of operator to a function reference?
>
> #include <above_stuff>
>
> int main() {
>     ftype& rf = f;
>     ftype* pf = &rf; // VC++ compile time error /* I corrected your example
>     return 0;            // as I thought you meant '&rf' and not '&f' */
> }

This is perfectly all right again, as you can always apply the
built-in '&' operator to an lvalue, and it will be interpreted as
specified in Clause 5 of the Standard. E.g. in the above example the
expression '&rf' has a type of 'void(*)()', which is exactly the type
that the initialization calls for.


> VC++ won't compile this at all, but it seems to me that the operator should work
> with regards to what is being referenced rather than the reference itself.

> Basically, I'm wondering if function references are special cases in the
> standard.

No they aren't, try thinking in terms of lvalues and rvalues when it
comes to binding references or using the built-in 'operator&'.


Regards,

Andrei Iltchenko.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]