Template functor cannot infer reference type

I have a functor f that takes a func function and a parameter t of the same type as func. I cannot pass g to f due to a compilation error (there is no corresponding function to call f(int&, void (&)(int&)) ). If g accepts a non-reference parameter g (int s), compilation is completed. Or, if I manually specify the template parameter f<int&>(i, g) , compilation will also end.

 template<typename T> void f(T t, void (*func)(T)) {} void g(int& s) {} int main(int, char*[]) { int i = 7; f(i, g); // compilation error here return 0; } 

How can I make deduction work?

+4
source share
4 answers

You can call the function as follows:

 f<int&>(i, g); 

But now I will follow the link too.

In general, I would make the function also a template type:

 template <typename T, typename F> void f(T t, F func) { func(t); //eg } 
+6
source

I think you need:

 void f(T t, void (*func)(T&)) {} 

or

 void g(int s) {} 

but I prefer:

 template<typename T, typename T2> void f(T t, T2 func) {} 

as this will work with functions and functors.

+5
source

The problem is that if in the template one of its functional parameters is not a reference type before deduction begins, this parameter will never output to the reference type. Thus, in the output on the left side of T get int , but in the output on the right side of T get int& . This complainer and compiler complain.

It is best to make the function parameter the same type as the function pointer parameter type:

 template<typename T> struct identity { typedef T type; }; template<typename T> void f(typename identity<T>::type t, void (*func)(T)) {} 

Using identity<T>::type , you turn off the residue on the left side. After determining T on the right side, T lingers on the left side and gives the final parameter type.

One guy suggested taking the right side as a template parameter - this is good, because after that he can overload functional objects with operator() . But you are faced with the problem of knowing if he wants a link or not. To solve this problem, boost has a reference_wrapper (by the way, boost also has an identity template above).

 template<typename T, typename F> void f(T t, F func) {} 

Now, if you want to pass a link, not a copy, you can do it like this

 int i; f(boost::ref(i), some_function); 

ref returns a reference_wrapper object that is implicitly converted to T& . Therefore, if you call func(t) , T automatically converted to the target link. If you do not want to pass the link, just pass i directly.

+5
source
 template<typename T> void f(T t, void (*func)(T)) {} 

The main thing is that you used T in both arguments. This means that the types must match exactly.

 void g(int& s) {} int i = 7; f(i, g); 

In your code, you pass an int and a function from int& to f() . These are different types, but your template for f expects two types to be the same . The easiest fix, as others have suggested, is to make the function a template.

 template <typename T, typename F> void f(T t, F func) { func(t); } 
+1
source

Source: https://habr.com/ru/post/1305465/


All Articles