如何将模板成员函数指针作为模板模板非类型参数传递?
解决模板成员函数指针作为非类型模板参数传递的问题
我明白你想实现的目标——把Impl结构体里的某个模板成员函数(比如LookupMat_1)的指针,作为非类型模板参数传给另一个模板成员函数对吧?这里的核心难点是模板成员函数本身不是一个可直接寻址的实体,必须先实例化(指定具体的Unit参数)才能得到有效的函数指针,同时要正确声明非类型模板参数的类型。
先补全你的基础代码
首先把你给出的代码补全成可编译的结构:
enum Unit { model_unit, nanometers, meters }; struct Material { double rho; }; struct Point { double x, y, z; }; struct Impl{ template<Unit unit> Material* LookupMat_1(const Point& p) { return nullptr; // 假设此处返回有效指针 } template<Unit unit> Material* LookupMat_2(const Point& p) { return nullptr; // 实现逻辑 } };
方案1:明确声明成员函数指针类型的非类型模板参数
我们可以给Impl添加一个模板成员函数UseLookup,它的模板参数包含两个部分:Unit枚举值,以及匹配的成员函数指针类型:
struct Impl{ // ... 保留原有的LookupMat_1和LookupMat_2 ... // 模板参数:指定unit,以及对应的成员函数指针 template<Unit unit, Material* (Impl::*LookupFunc)(const Point&)> Material* UseLookup(const Point& p) { // 通过成员函数指针调用对应方法 return (this->*LookupFunc)(p); } };
调用的时候,需要明确指定unit和实例化后的成员函数指针:
int main() { Impl obj; Point p{}; // 使用LookupMat_1<model_unit>作为参数 auto mat1 = obj.UseLookup<model_unit, &Impl::LookupMat_1<model_unit>>(p); // 使用LookupMat_2<nanometers>作为参数 auto mat2 = obj.UseLookup<nanometers, &Impl::LookupMat_2<nanometers>>(p); }
方案2:用C++17的auto非类型模板参数简化写法
如果你使用C++17或更高版本,可以利用auto自动推导非类型模板参数的类型,省去手动声明函数指针类型的麻烦:
struct Impl{ // ... 保留原有的LookupMat_1和LookupMat_2 ... template<auto LookupFunc> Material* UseLookupAuto(const Point& p) { return (this->*LookupFunc)(p); } };
调用时只需要传入实例化后的成员函数指针即可,编译器会自动推导类型:
int main() { Impl obj; Point p{}; auto mat1 = obj.UseLookupAuto<&Impl::LookupMat_1<model_unit>>(p); auto mat2 = obj.UseLookupAuto<&Impl::LookupMat_2<nanometers>>(p); }
关键注意点
- 模板成员函数(比如
LookupMat_1)本身不是一个具体的函数,必须指定Unit参数实例化后,才能得到可传递的函数指针。 - 非类型模板参数的类型必须和实例化后的成员函数指针类型完全匹配,否则编译器会报错。
内容的提问来源于stack exchange,提问作者ThreeStarProgrammer57
相关产品推荐
相关产品推荐

