[英]Calling template function with non-type template parameter using class attribute
假设您有一个名为Func
的enum class
,一个具有Func
属性的类和一个包含函数模板compute
的Functions
类:
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.
}
}
我想通过传递func
属性从Functions
调用适当的专用模板。 但是,这不起作用,因为在编译时不知道func
。 我在clang
收到以下错误:
candidate template ignored: invalid explicitly-specified argument for template parameter 'fn'
^
我相信我可以通过将Foo
的compute
方法也设为模板并专门针对每个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.
但是,这违反了目的,因为我想在Foo
使用func
属性。 另外,我想避免双重处理,因为Foo::compute()
会执行更多操作,我必须将这些操作复制到每个专业化中。
是否可以通过使用func
属性来实现此功能?
模板解析是一种完全编译时的机制。 在这种情况下,您需要某种方式在运行时选择调用哪个函数:函数指针,虚函数,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.
}
}
您不必专门研究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.
}
};
您无法使用模板解决此问题。 模板解析追加和编译时间,您想选择一个运行时。 有很多解决方案,例如提出的解决方案,但是没有一个将使用模板。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.