[C++] Function References

Started by
12 comments, last by theOcelot 14 years, 1 month ago
It just recently came to my attention that there are probably a lot of C++ programmers out there that don't know about function references. People discuss function pointers from time to time, but almost never discuss function referencs. It's hard to find any info about them on the web too. I've actually been using them for a few years now. Example usage:
typedef int Func(int x);

int bar2(int x) { return x*2; }
int bar3(int x) { return x*3; }

void foo(Func &foobar)
{
    std::cout << foobar(5);
}

int main()
{
    foo(bar2);
    foo(bar3);
}
As you can see, they are actually cleaner to use than function pointers! Also, just like the difference between regular pointers and references, function references can't be made to point to a different function, and can't be NULL. Surely they'd thererfore allow for more optimisation possibilities? The only thing that isn't the same as regular references is that there's no usefulness to making them const. i.e.
void foo(const Func &foobar)
Such code causes the following in VS2008:
warning C4180: qualifier applied to function type has no meaning; ignored
Does anyone have any thoughts as to why they might not be very popular? Should we actually be preferring these over function pointers for the same reasons that we should prefer regular references over pointers? Do they work equally as well on all compilers?
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Advertisement
But these are function pointers. Just passed by reference, which is irrelevant in this particular case.

Or am I missing something.

The following also works:
template < class Func >void foo(Func f) {  f(14);}...foo(bar);
Quote:Original post by iMalc
Does anyone have any thoughts as to why they might not be very popular?

I'd guess because most of the time both function pointers and function references are too low level and people grab a function object like boost::function instead.
Quote:Original post by Antheus
But these are function pointers. Just passed by reference, which is irrelevant in this particular case.

Or am I missing something.

The following also works:
template < class Func >void foo(Func f) {  f(14);}...foo(bar);


Not quite. If they were function pointers passed by reference, you could do this:

typedef void (&func_ref)();typedef void (*func_ptr)();void do_something(func_ref ref){   func_ptr ptr;   ref = ptr;}


You can, however, do this:

void foo(func_ptr& ptr_ref){	func_ptr ptr;	ptr_ref = ptr;}


so, they are a little different. Instead of being a function POINTER passed by reference it is the actual function passed by reference. To prove this compare typeid(void(&)()) to typeid(void()()) and they'll compare equal by operator==, yet both will compare different to typeid(void(*)());

I think in general function references aren't terribly useful for the same reason that function pointers aren't terribly useful. Most of the time if you want to take arbitrary function types you are either templating on the the function type, as Antheus did so that you can take anything that looks like a function, or if you need to be able to store it for later invocation, then using boost::function.
Interesting info thanks.

I don't really know much about boost::function. I found this which describes the differences between boost::function and function pointers. Unfortunately not being one who's properly gotten into boost yet, it's hard to appreciate the value boost::function has.

The main place I've used function references is in a Sutherland-Hodgman clipping algorithm for performing clipping in 3D.
By having functions that take a point and return say the difference between the Z and X coordinates (for clipping against the right hand-side of the fustrum) or various other combinations, I implemented my clipper without using templates. I've seen other's use templates for the same thing but it just felt wrong instantiating 6 versions of the same function that can differ by about as much as a plus instead of a minus. I could have very well used function pointers instead of course.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Let's have type X:
void foo(X x);void foo(X &x);void foo(X *x);


Are there any different rules for function pointers when passed via above forms than they are for all other types?

It seems to me that they should follow same rules. X is function, *X is function pointer, &X is reference to function - but they all deal with same type.

Quote:
void do_something(func_ref ref){   func_ptr ptr;   ref = ptr;}

Shouldn't that be: 'ref = *ptr'?
Quote:Original post by Antheus
Let's have type X:
void foo(X x);void foo(X &x);void foo(X *x);


Are there any different rules for function pointers when passed via above forms than they are for all other types?

It seems to me that they should follow same rules. X is function, *X is function pointer, &X is reference to function - but they all deal with same type.

Quote:
void do_something(func_ref ref){   func_ptr ptr;   ref = ptr;}

Shouldn't that be: 'ref = *ptr'?


Well that was kind of my point, that they aren't compatible. I was just responding to your comment that function references are actually function pointers, just passed by reference. If that were true, then the above should compile, because "reference to function pointer" and "function pointer" should be compatible.

Functions (and pointers and references) kind of break standard rules anyway though, which is part of why they're confusing, since for example you can do things like:

func_ptr ptr = &foo;func_ptr ptr = foo;


and they mean the same thing.
Quote:Original post by cache_hit
You can, however, do this:

*** Source Snippet Removed ***

so, they are a little different. Instead of being a function POINTER passed by reference it is the actual function passed by reference.


Huh? Your code passes 'func_ptr&', and func_ptr is a function pointer type. How is that not "a function pointer passed by reference"?
That obviously *is* a reference to a function pointer. However, i was responding to the claim that "a function reference is a function pointer, passed by reference.". If that were true, then func_ref should be the same as func_ptr&, unless im missing something (which is certainly possible given my spaciness the past few days). Thats what the example was intended to illustrate
Quote:Original post by iMalc
function references can't be made to point to a different function, and can't be NULL.

Does anyone have any thoughts as to why they might not be very popular?

I believe you answered your own question.

Those are among the most useful features of function pointers. You can allow the function users to pass in NULL, with the meaning "don't call any function". You can allow the function users to set the function for a time, and replace it with a new one as they deem it appropriate.

Your optimization question is interesting. I would think the optimizer would see no difference between this and a more traditional function pointer. In both cases it is nothing more than accepting an address as a parameter, and then pushing parameters and jumping to the address. The optimizers would recognize both as function pointers, so it would optimize it the same.

This topic is closed to new replies.

Advertisement