如何解决非类型参数模板函数,错误:必须调用对非静态成员函数的引用
我正在尝试使用非类型参数模板函数作为类的成员,但遇到了错误。下面是一个最小的工作示例
#include <iostream>
enum Mode {ka,kb,kab};
class Foo {
public:
Foo(const double& x = 1.0,const Mode& y = ka) : x_(x),y_(y) {;}
Mode get() const{
return y_;
}
template<Mode mode> double FooFunc();
private:
double x_;
Mode y_;
};
template<> double Foo::FooFunc<ka>() {
return 1/x_;
}
template<> double Foo::FooFunc<kb>() {
return 1/x_/x_;
}
template<> double Foo::FooFunc<kab>() {
return 1/x_/x_/x_;
}
int main() {
Foo foo1(2,ka),foo2(2,kb),foo3(2,kab);
std::cout << "foo1 function result: " << foo1.FooFunc<foo1.get()> << "\n";
std::cout << "foo2 function result: " << foo2.FooFunc<foo2.get()> << "\n";
std::cout << "foo3 function result: " << foo3.FooFunc<foo3.get()> << "\n";
return 0;
}
我正在用 clang 编译它,如下c++ foo.cpp -o foo -O3 -std=c++11
。这会导致以下错误,我不确定是什么问题。任何帮助将不胜感激。
foo.cpp:34:48: error: reference to non-static member function must be called
std::cout << "foo1 function result: " << foo1.FooFunc<foo1.get()> << "\n";
~~~~~^~~~~~~~~~~~~~~~~~~
foo.cpp:12:30: note: possible target for call
template<Mode mode> double FooFunc();
^
foo.cpp:35:48: error: reference to non-static member function must be called
std::cout << "foo2 function result: " << foo2.FooFunc<foo2.get()> << "\n";
~~~~~^~~~~~~~~~~~~~~~~~~
foo.cpp:12:30: note: possible target for call
template<Mode mode> double FooFunc();
^
foo.cpp:36:48: error: reference to non-static member function must be called
std::cout << "foo3 function result: " << foo3.FooFunc<foo3.get()> << "\n";
~~~~~^~~~~~~~~~~~~~~~~~~
foo.cpp:12:30: note: possible target for call
template<Mode mode> double FooFunc();
^
3 errors generated.
解决方法
您的代码的问题在于模板参数必须是编译时常量。对于函数调用,这意味着它必须是 constexpr
,而对于类方法,这意味着它必须是 static
。
你只有两个选择:
-
要么将
Mode
的配置留给运行时,并允许用户潜在地重新配置Mode
。为此,您必须在函数内引入if
/else
或switch
语句。class Foo { public: constexpr Foo(double const x = 1.0,Mode const y = Mode::ka) noexcept : x_{x},y_{y} { return; } Mode get() const noexcept { return y_; } double FooFunc() const { switch (y_) { case Mode::ka: return 1.0/x_; case Mode::kb: return 1.0/x_/x_; case Mode::kab: return 1.0/x_/x_/x_; default: // Throw error } } private: double x_; Mode y_; };
-
如果您不打算让用户随时更改
Mode
,您可以将其设为类模板并专门化相应的功能。这样,虽然无法即时更改模式。template <Mode M = Mode::ka> class Foo { public: constexpr Foo(double const x = 1.0) noexcept : x_(x) { return; } static constexpr Mode get() noexcept { return M; } double FooFunc() const noexcept; private: double x_; Mode y_; }; template<> inline double Foo<Mode::ka>::FooFunc() const noexcept { return 1.0/x_; } template<> inline double Foo<Mode::kb>::FooFunc() const noexcept { return 1.0/x_/x_; } template<> inline double Foo<Mode::kab>::FooFunc() const noexcept { return 1.0/x_/x_/x_; }
使用 constexpr
,您可以:
enum Mode {ka,kb,kab};
class Foo {
public:
constexpr Foo(const double& x = 1.0,const Mode& y = ka) : x_(x),y_(y) {}
constexpr Mode get() const{
return y_;
}
template<Mode mode> constexpr double FooFunc() const;
private:
double x_;
Mode y_;
};
template<> constexpr double Foo::FooFunc<ka>() const {
return 1/x_;
}
template<> constexpr double Foo::FooFunc<kb>() const {
return 1/x_/x_;
}
template<> constexpr double Foo::FooFunc<kab>() const {
return 1/x_/x_/x_;
}
int main() {
constexpr Foo foo1(2,ka),foo2(2,kb),foo3(2,kab);
std::cout << "foo1 function result: " << foo1.FooFunc<foo1.get()>() << "\n";
std::cout << "foo2 function result: " << foo2.FooFunc<foo2.get()>() << "\n";
std::cout << "foo3 function result: " << foo3.FooFunc<foo3.get()>() << "\n";
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。