C++14中能否实现带模板参数的函数指针模板?编译问题求助
在C++14中实现接收带模板参数的可调用对象的函数
你的原代码编译失败的核心原因是:add是一个模板函数,而非具体的函数实例,没法直接作为非类型模板参数传递给execF——非类型模板参数要求是编译期可见的具体实体(比如实例化后的函数指针、常量值等)。不过别担心,C++14完全能实现你想要的功能,而且有几种灵活的方案:
方案1:传递可调用对象作为函数参数(最推荐)
这种方式不需要把可调用对象放到模板参数里,而是直接作为函数参数传递,利用C++14的自动类型推导和泛型lambda特性,灵活性拉满:
#include <iostream> // 通用的execF,接受任意可调用对象和两个同类型参数 template <class F, class T> T execF(F f, T a, T b) { return f(a, b); } // 原有的模板add函数 template <class T> T add(T a, T b) { return a + b; } int main() { // 传递实例化后的add<int>函数指针 std::cout << execF(add<int>, 3, 4) << std::endl; // 更方便的:用C++14泛型lambda直接实现加法,无需提前定义模板函数 std::cout << execF([](auto a, auto b) { return a + b; }, 3, 4) << std::endl; }
方案2:将实例化后的函数指针作为非类型模板参数
如果你坚持要把函数放到模板参数里,可以传递实例化后的函数指针(此时它是编译期常量):
#include <iostream> template <class T, T (*F)(T, T)> T execF(T a, T b) { return F(a, b); } template <class T> T add(T a, T b) { return a + b; } int main() { // 这里必须传递add<int>(实例化后的函数指针),而非模板本身add std::cout << execF<int, add<int>>(3, 4) << std::endl; }
不过这种方式的缺点是灵活性差,每次都要显式指定add的实例化类型,没法自动适配不同的T。
方案3:使用仿函数类作为模板参数
如果你想让可调用对象本身支持泛型操作,可以定义一个重载operator()的仿函数类,将其作为类型模板参数传递:
#include <iostream> template <class F, class T> T execF(T a, T b) { // 创建仿函数实例并调用operator() return F{}(a, b); } // 泛型仿函数,支持任意类型的加法 struct Add { template <class T> T operator()(T a, T b) const { return a + b; } }; int main() { std::cout << execF<Add>(3, 4) << std::endl; // 也可以直接用于其他类型,比如double std::cout << execF<Add>(2.5, 3.5) << std::endl; }
这种方式兼顾了模板参数传递和泛型操作的灵活性,适合需要复用可调用逻辑的场景。
总结
C14完全支持你想要的功能,其中**方案1(传递可调用对象作为函数参数)**是最灵活、最符合现代C风格的选择,尤其是搭配泛型lambda使用时,几乎不需要额外的模板定义就能实现通用的函数调用逻辑。
内容的提问来源于stack exchange,提问作者amon880
相关产品推荐
相关产品推荐

