我想将(指向模板成员函数)指向另一个模板成员函数的指针作为模板模板非类型参数传递。
这是我尝试过的:
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; // let's suppose it returns a valid pointer
}
template<Unit unit>
Material * LookupMat_2(const Point& p) {
return nullptr; // let's suppose it returns a valid pointer
}
// compiler error here:
// expected 'class' or 'typename' before 'Material'
// template<template<Unit> Material * (Impl::*LookupFunc)(const Point&)
// ^~~~~~~~
template<template<Unit> Material * (Impl::*LookupFunc)(const Point&) >
Material * GetMaterial(const Point & p) {
return (this->*LookupFunc<Unit::model_unit>)(p);
}
void DoSomething() {
Point p = {};
auto mat_1 = GetMaterial<LookupMat_1>(p);
auto mat_2 = GetMaterial<LookupMat_2>(p);
}
};
int main() {
Impl i;
i.DoSomething();
}
我的语法错了,编译器说:
main.cpp:25:29: error: expected 'class' or 'typename' before 'Material' template<template<Unit> Material * (Impl::*LookupFunc)(const Point&) ^~~~~~~~
我无法弄清楚正确的语法。
LookupFunc
是Material * (Impl::*)(const Point&)
类型的模板,它是指向成员函数的指针。
我正在尝试做什么?
我错过了什么?
答案 0 :(得分:3)
正如评论中所解释的那样,没有一个指向模板函数(或方法)的指针,因为它不是一个函数,而是一组函数。
我能想象做的最好的事情(我的意思是......在Unit
中解释GetMaterial()
类型)是在Impl
中添加一些静态的子结构模板方法
struct lm1
{
template <Unit U>
static Material * func (Point const & p)
{ return nullptr; }
};
struct lm2
{
template <Unit U>
static Material * func (Point const & p)
{ return nullptr; }
};
然后按以下方式重写GetMaterial()
template <typename T>
Material * GetMaterial (Point const & p)
{ return T::template func<Unit::model_unit>(p); }
并以这种方式使用
void DoSomething()
{
Point p = {};
auto mat_1 = GetMaterial<lm1>(p);
auto mat_2 = GetMaterial<lm2>(p);
}
通过这种方式,您可以向GetMaterial()
传递包含完整模板函数集的单个类型(lm1
或lm2
);然后,在GetMaterial()
内,选择正确的函数来解释Unit::model_unit
。
以下是一个完整的工作示例
enum Unit { model_unit, nanometers, meters };
struct Material
{ double rho; };
struct Point
{ double x, y, z; };
struct Impl
{
struct lm1
{
template <Unit U>
static Material * func (Point const & p)
{ return nullptr; }
};
struct lm2
{
template <Unit U>
static Material * func (Point const & p)
{ return nullptr; }
};
template <typename T>
Material * GetMaterial (Point const & p)
{ return T::template func<Unit::model_unit>(p); }
void DoSomething()
{
Point p = {};
auto mat_1 = GetMaterial<lm1>(p);
auto mat_2 = GetMaterial<lm2>(p);
}
};
int main ()
{
Impl i;
i.DoSomething();
}
答案 1 :(得分:3)
这里是类模板作为仿函数的方式。
template<Unit unit>
struct LookupMat_1
{
Material * operator()(const Point& p) {
return nullptr;
}
};
template<Unit unit>
struct LookupMat_2
{
Material * operator()(const Point& p) {
return nullptr;
}
};
template<template<Unit> typename LookupMat>
Material * GetMaterial(const Point & p)
{
return LookupMat<Unit::model_unit>()(p);
}