如何将函数模板作为另一个模板的模板参数?
如何将函数模板作为另一个模板的模板参数?
你遇到的问题核心在于:函数模板不能直接作为模板模板参数传递。编译器报错是因为proxy1的模板参数template<typename> typename func期望的是一个类模板/变量模板,但function是函数模板,两者类型不匹配,所以找不到对应的重载。
下面给你两种可行的解决方法:
方法一:将函数模板包装为类模板的静态成员函数
我们可以把函数模板的逻辑放到类模板的静态成员函数里,这样类模板就符合proxy1对模板模板参数的要求了:
#include <iostream> // 原函数模板 template <typename T> T function() { std::cout << "Called function<" << typeid(T).name() << ">()\n"; return T(); } // 包装成类模板的静态成员 template <typename T> struct FunctionWrapper { static T call() { return function<T>(); } }; // 复用你原来的proxy1模板参数写法 template<template<typename> typename func> void proxy1(int x) { if (x == 0) func<bool>::call(); else if (x == 1) func<int>::call(); } // 原proxy函数(作为对比) void proxy(int x) { if (x == 0) function<bool>(); else if (x == 1) function<int>(); } int main() { proxy1<FunctionWrapper>(0); // 现在可以正常调用了 proxy(0); }
方法二:使用C17的auto模板参数+constexpr lambda(C20及以上)
如果你用的是C++20或更高版本,可以借助constexpr lambda包装函数模板,配合auto模板参数实现更简洁的写法:
#include <iostream> #include <functional> // 用于std::invoke // 原函数模板 template <typename T> T function() { std::cout << "Called function<" << typeid(T).name() << ">()\n"; return T(); } // 调整proxy1的模板参数为auto,接受可调用对象 template <auto Callable> void proxy1(int x) { if (x == 0) { std::invoke(Callable.template operator()<bool>()); } else if (x == 1) { std::invoke(Callable.template operator()<int>()); } } // 原proxy函数(作为对比) void proxy(int x) { if (x == 0) function<bool>(); else if (x == 1) function<int>(); } int main() { // 定义constexpr lambda包装函数模板 constexpr auto func_wrapper = []<typename T>() { return function<T>(); }; proxy1<func_wrapper>(0); // 正常调用 proxy(0); }
补充说明:为什么原来的写法不行?
模板模板参数(比如template<typename> typename func)的设计初衷是匹配类模板或变量模板,而函数模板属于另一种模板类型,无法直接匹配这个参数约束。所以我们需要通过包装的方式,把函数模板转换成符合要求的模板类型。
内容来源于stack exchange
相关产品推荐
相关产品推荐

