简体   繁体   中英

Passing a templated functor as an argument to a templated function in C++

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM