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)?

4 Answers 4

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?"

Sign up to request clarification or add additional context in comments.

2 Comments

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.
Why does Test<void(int)>( &Callback ); work? Is a function pointer also implicitly convertible to its "value type"?
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.

3 Comments

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.
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?
@deft I don't know what that means. What's a "function value"?
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.

1 Comment

Maybe it's worth noting than there are languages where “function by value” does make sense.
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.