假设您有一个名为enum class
的{{1}},一个Func
属性的类和一个包含函数模板Func
的{{1}}类:
Functions
我想通过传递compute
属性来调用enum class Func
{
Sin,
Cos
// Others...
}
class Functions
{
public:
template<Func fn>
static inline double compute(const std::vector<double>& _args);
}
template<>
inline double compute<Func::Sin>(const std::vector<double>& _args)
{
return std::sin(std::accumulate(_args.begin(), _args.end(), 0.0));
}
template<>
inline double compute<Func::Cos>(const std::vector<double>& _args)
{
return std::cos(std::accumulate(_args.begin(), _args.end(), 0.0));
}
// More specialisations...
class Foo
{
private:
Func func;
double result;
public:
inline void compute(const std::vector<double>& _args)
{
result = Functions::compute<func>(_args);
// A few other operations follow.
}
}
中相应的专用模板。但是,这不起作用,因为在编译时不知道Functions
。我在func
中收到以下错误:
func
我相信我可以通过在clang
模板中设置candidate template ignored: invalid explicitly-specified argument for template parameter 'fn'
^
方法并专门针对每个compute
来实现这一目标:
Foo
然而,这违背了目的,因为我想使用Func
中的class Foo
{
private:
Func func;
double result;
public:
template<Func fn>
inline void compute(const std::vector<double>& _args)
{
result = Functions::compute<fn>(_args);
// A few other operations follow.
}
}
template<>
inline void compute<Func::Sin>()(const std::vector<double>& _args)
{
result = Functions::compute<Func::Sin>(_args);
}
template<>
inline void compute<Func::Cos>()(const std::vector<double>& _args)
{
result = Functions::compute<Func::Cos>(_args);
}
// Etc.
属性。另外,我想避免双重处理,因为func
执行了一些操作,我必须将其复制到每个专门化中。
有没有办法通过使用Foo
属性来实现此功能?
答案 0 :(得分:3)
模板解析是一种完全编译时的机制。在这种情况下,你需要一些方法在运行时选择调用哪个函数:函数指针,虚函数,switch语句......
使用函数指针的示例:
typedef double (*Func)(const std::vector<double>&);
double Sin(const std::vector<double>& args) {
return std::sin(args[0]);
}
// etc.
class Foo
{
private:
Func func;
double result;
public:
inline void compute(const std::vector<double>& _args)
{
result = func(_args);
// A few other operations follow.
}
}
答案 1 :(得分:1)
您不必专门化Foo::compute
。您可以直接使用通用定义:
template<Func fn>
void compute(const std::vector<double>& _args)
{
result = Functions::compute<fn>(_args);
// A few other operations follow.
}
如果要将运行时成员转换为编译时值,则必须自行调度。 switch
或数组是可能的方式
class Foo
{
private:
Func func;
double result;
public:
void compute(const std::vector<double>& _args)
{
switch (func) {
case Func::Sin: result = Functions::compute<Func::Sin>(_args); break;
case Func::Cos: result = Functions::compute<Func::Cos>(_args); break;
// ...
}
// A few other operations follow.
}
};
答案 2 :(得分:1)
您无法使用模板解决此问题。模板解析附加和编译时间,您想要选择运行时。 有许多解决方案,例如提议的解决方案,但没有一个会使用模板。