pass function by value (?) instead of function pointer?
Asked Answered
D

4

15

Sorry if this has been asked before, but I was unable to find it.

So im trying to educate myself about templates and the new C++11 features (mainly lambdas, something I always liked in other languages).

But in my tests I came to something I had no idea it worked, and I'm trying to understand how it works but cant figure it out..

The following code:

template <class Func>
void Test( Func callback ) {
    callback( 3 );
}

void Callback( int i ) {
    std::cout << i << std::endl;
}

int main( int argc, char** argv ) {
    Test( &Callback ); // this I was expecting to work, compiler will see its a pointer to a function
    Test( Callback ); // this also works, but how?!
    return 0;
}

If I understand how templates work, basically they're a scheme for the compiler to know what to build, so the first call Test( &Callback ); I was expecting to work because the compiler will see the template receives a function address and will assume the arguments should be a pointer.

But what is the second call? What is the template assuming it is? A copy of a functio (if that even makes any sense)?

Darondarooge answered 18/8, 2011 at 17:2 Comment(0)
O
19

A function is implicitly convertible to a pointer to itself; this conversion happens pretty much everywhere. Test(Callback) is exactly the same as Test(&Callback). There is no difference. In both cases, Func is deduced to be void(*)(int).

Function pointers are weird. You can find out more about them in "Why do all these crazy function pointer definitions all work?"

Obduliaobdurate answered 18/8, 2011 at 17:3 Comment(2)
thanks for the answer. so if i didnt use templates and declared Test like: void Test( void (*callback)(int) ){...} both calls would work as well. thats good to know. ill make sure i read the thread you linked.Darondarooge
Why does Test<void(int)>( &Callback ); work? Is a function pointer also implicitly convertible to its "value type"?Boughpot
C
3

Functions are implicitly convertible to function pointers. If fact there is no way to get a function value or reference. Though oddly you can create a function value type, you just can't assign anything to it.

Here is code snippit that demonstrates how lambdas and various callbacks react with templates.

Chokecherry answered 18/8, 2011 at 17:21 Comment(3)
This is wrong. Function references are fine. If Test were declared as void Test( Func &callback ), then Func would be deduced to void(int), and Callback would be passed by reference, without being converted to a pointer, to Test.Sororicide
Wow! I guess it make sense that reference should be supported as well as pointers since they are so similar. Is it possible to declare a function value, and assign something to it?Chokecherry
@deft I don't know what that means. What's a "function value"?Sororicide
B
2

In C++, functions are not first-class objects, which means “function as value” makes no sense in it. That's why function name has always been implicitly convertible to pointer to it.

Blacking answered 18/8, 2011 at 17:8 Comment(1)
Maybe it's worth noting than there are languages where “function by value” does make sense.Blacking
V
0

In C++ 11 (and boost and tr1) we have std::function as a template type for storing functors, lambdas and functions. So you can definitely have the concept of keeping a function value in a variable of type std::function. that variable can also be "empty" meaning that no function (reference) is stored in it. Then it cannot be called.

The original question relates to that in contrast to C, C++ allows function references. Plus, for compatibility reasons with C a function name can degenerate to a function pointer. But because of overloading things are more "interesting" in C++ than in C.

Vilayet answered 20/10, 2011 at 8:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.