使用 class 属性调用带有非类型模板参数的模板函数
Calling template function with non-type template parameter using class attribute
假设您有一个名为 Func
的 enum class
,一个具有 Func
属性的 class 和一个包含函数的 Functions
class模板 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.
}
}
我想通过传递 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
属性来实现这个功能?
模板解析是一种完全编译时的机制。在这种情况下,您需要一些方法 select 在运行时调用哪个函数:函数指针、虚函数、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.
}
};
您无法使用模板解决此问题。模板解析附加和编译时间,你想选择一个 运行 时间。
有很多解决方案,例如所提出的解决方案,但其中 none 将使用模板。
假设您有一个名为 Func
的 enum class
,一个具有 Func
属性的 class 和一个包含函数的 Functions
class模板 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.
}
}
我想通过传递 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
属性来实现这个功能?
模板解析是一种完全编译时的机制。在这种情况下,您需要一些方法 select 在运行时调用哪个函数:函数指针、虚函数、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.
}
};
您无法使用模板解决此问题。模板解析附加和编译时间,你想选择一个 运行 时间。 有很多解决方案,例如所提出的解决方案,但其中 none 将使用模板。