将模板函数作为普通函数的参数传递

Passing template function as argument for normal function

本文关键字:函数 参数传递      更新时间:2023-10-16

我想知道是否可以将模板函数(或其他函数)作为参数传递给第二个函数(不是模板)。向谷歌询问这一点似乎只提供了相反的信息(作为模板参数传递的函数)

我能找到的唯一相关页面是 http://www.beta.microsoft.com/VisualStudio/feedbackdetail/view/947754/compiler-error-on-passing-template-function-as-an-argument-to-a-function-with-ellipsis(不是很有帮助)

我期待这样的东西:

template<class N>void print(A input){cout << input;}
void execute(int input, template<class N>void func(N)){func(input)}

然后打电话

execute(1,print);

那么,可以这样做还是必须为 execute() 定义另一个模板?

函数模板表示无限重载集,因此除非您具有与专用化兼容的目标类型,否则函数类型的推导总是失败。例如:

template<class T> void f(T);
template<class T> void h(T);
void g() {
    h(f); // error: couldn't infer template argument 'T'
    h(f<int>); // OK, type is void (*)(int)
    h<void(int)>(f); // OK, compatible specialization
}

从上面我们可以看到,程序的有效性要求我们为函数模板指定模板参数,而一般来说,指定它们并不总是直观的。您可以改为使用通用重载调用运算符将print函子作为额外的间接级别:

struct print {
     template<typename T>
     void operator()(T&& x) const {
         std::cout << x;
     }
};

现在,您可以让execute接受任何 Callable 并使用输入调用它:

template<class T, class Op>
void execute(T&& input, Op&& op) {
    std::forward<Op>(op)(std::forward<T>(input));
}
void g() { execute(1, print{}); }

通用 lambda (C++14) 使它更加简洁:

execute(1, [] (auto&& x) { std::cout << x; });

执行需要是一个模板 - 编译器无法创建适用于任何输入类型的单个版本的 execute。 现在,如果您为此特定函数指定了 N 是什么 - 例如,如果您制作了第二个参数 print- 那么它应该是合法的。