I am trying to pass a templated functor into a templated function. The code looks something like this:
template<typename T>
T func_1(T &a) {
return a;
}
template <typename T>
T test(T &a, std::function<T(T&)> &func){
return func(a);
}
int main(){
int a = 5;
std::cout << test(a, func_1) << std::endl;
}
However, I get the following compile error:
invalid initialization of non-const reference of type 'std::function<int(int&)>&' from an rvalue of type ''
The code works if I remove the template. Can someone help me understand why?
func_1
is function template. You have to pass a concrete type you want this function to be instantiated. In your case it is int
, type of a
variable.
std::cout << test(a, func_1<decltype(a)>) << std::endl;
Then, function
object can be created taking func_1<int>
instantiation. This function is temporary, but temporary cannot be bound to Lvalue reference, so signature of test
should be modified to accept const Lvalue ref:
template <typename T>
T test(T &a, const std::function<T(T&)> &func){
// <---- const
return func(a);
}
The issue is that func_1
is just a template, to get a function pointer you first need a function (ie an instantiation of the function template).
You can get what you want by making func_1
an actual functor (ie callable object) that is not a template itself:
#include <functional>
#include <iostream>
struct func_1 {
template <typename T>
T operator()(T& a){ return a; }
};
template <typename T,typename F>
T test(T &a, F func){
return func(a);
}
int main(){
int a = 5;
std::cout << test(a, func_1{}) << std::endl;
// ^^ create instance
}
The "trick" is that only func_1::operator()
is a template, so you can create objects of func_1
and pass them around before you know what T
actually is. The operator is only instantiated when it is called in test
but not in main
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.