mixing &fun and fun in same function call

My understanding is that function arguments are always passed by reference whether prefixed with & or not. However, it seems that GCC gets confused when the two forms are mixed in a templated function declaration.

I somehow understand why it is stylistically unadvisable to mix the two forms but I don’t understand why it would not compile anyway.

what is the rationale?

In the attached code, fluke3 does not compile because the calling signature cannot be matched to one of the available templates. (error: no matching function for call to ‘fluke3(int (&)(int), int (&)(int))’)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>

template<class F>
int  fluke1(F  fun, F  foo){
 return foo(fun(1));
}


template<class F>
int  fluke2(F  & fun, F &  foo){
 return foo(fun(2));
}



template<class F>
int  fluke3(F  fun, F &  foo){
 return foo(fun(3));
}

int doubler(int x){return 2 * x;}


int main(){
    std::cout<<fluke1(doubler,doubler)<<std::endl;
    std::cout<<fluke2(doubler,doubler)<<std::endl;
    std::cout<<fluke3(doubler,doubler)<<std::endl;  //does not compile!

}
Last edited on
A "note" after the error explains the problem:

note: deduced conflicting types for parameter ‘F’ (‘int (*)(int)’ and ‘int(int)’)

You could of course do this:

1
2
template<class F, class G>
int fluke3(F fun, G & foo){ return foo(fun(3)); }

But a function name is already a (constant) pointer so it seems kind of silly to pass a it by reference. What's the point?

Maybe you're getting confused by the different meanings of & in C++. For instance, you could call your fluke1 like this:

 
fluke1(&doubler, doubler); // &douber and doubler are the same here 

Last edited on
My understanding is that function arguments are always passed by reference whether prefixed with & or not.

That's incorrect: you're confusing pointers and references. If you prefix a function argument with a &, the type of the argument is a pointer (to function), and that cannot be used with a reference parameter., as the compiler told you.

Simpler repro

1
2
3
4
5
6
7
8
9
10
11
12
using F = int(int); // function type
// this function takes a function by preference
int g(F& f) {
    return f(1);
}

int dbl(int x) { return x*2; }
int main()
{
    g(dbl); // OK (pass by reference)
    g(&dbl); // Error: (function expects F&, but the argument is F*)
}


live demo https://wandbox.org/permlink/PyAW6rhIlnpKFJ0Y

But a function name is already a (constant) pointer

that's incorrect. A function name names that function. This is the same deal as with C-style arrays.
Last edited on
@cubbi

you're confusing pointers and references


Thanks for your response but my question was about template resolution. I probably confused you by writing " whether prefixed with & or not". I just meant that if F is a function type, whether an argument is declared as F& foo or F foo doesn't matter, it will always be a reference.
Last edited on
@dutch

Thanks for your reply, I do see that the problem is that the same template symbol can't be associated with both the
‘int (*)(int)’
and
‘int(int)’)
types.

However, as you point out, a function is always a pointer and there is never a value of type ‘int(int)’ (correct ?). Ultimately the reference type is substituted to the value type by the compiler (correct ?). So I had imagined that the substitution would also happen during template processing. Obviously, it is not the case. Perhaps, it is just the way it is because there is no real reason to do otherwise, perhaps the idea is just plain absurd, I am wondering.
Topic archived. No new replies allowed.