为什么成员函数不能用作模板参数?

Jun*_*eon 8 c++ templates member-functions

为什么成员函数不能用作模板参数?例如,我想这样做:

struct Foo {
    void Bar() { // do something
    }
};
template <typename TOwner, void(&func)()>
void Call(TOwner *p) {
    p->func();
}
int main() {
    Foo a;
    Call<Foo, Foo::Bar>(&a);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我知道使用指向成员的指针可以做类似的事情; 好吧,它大部分时间都很酷,但我只是好奇为什么指针"应该"使用.

我认为上面解释"p-> func()"没有含糊之处.为什么该标准禁止我们使用成员函数作为模板参数?根据我的编译器(VC++ 2013),甚至不允许使用静态成员函数.有谁知道原因?或者,有没有办法做同样的事情而不会因指针解除引用而失去任何性能?

谢谢.

use*_*267 24

它们可以用作非类型参数,但您需要使用正确的语法

struct Foo {
    void Bar() { // do something
    }
};
template <typename TOwner, void(TOwner::*func)()>
void Call(TOwner *p) {
    (p->*func)();
}
int main() {
    Foo a;
    Call<Foo, &Foo::Bar>(&a);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)


dav*_*igh 4

事实上,成员函数指针可以用作模板参数(就像任何其他指针类型可以用作模板参数一样):

\n\n
struct A\n{\n    int f(float x);\n};\n\ntemplate <int (A::F*)(float)>\nstruct B {};\n\ntemplate<A *> struct C;\ntemplate<A &> struct D;\n
Run Code Online (Sandbox Code Playgroud)\n\n

但是,根据以下 C++ 标准摘录,无法传递对成员的引用。

\n\n
\n

[温度参数]

\n\n
    \n
  1. 非类型模板参数应具有以下类型之一(可选 cv 限定):
  2. \n
\n\n

(4.1) \xe2\x80\x94 整型或枚举类型,

\n\n

(4.2) \xe2\x80\x94 指向对象的指针或指向函数的指针,

\n\n

(4.3) \xe2\x80\x94 对对象的左值引用或对函数的左值引用,

\n\n

(4.4) \xe2\x80\x94指向成员的指针,

\n\n

(4.5) \xe2\x80\x94 std::nullptr_t。

\n
\n\n


\n\n
\n\n

接下来,假设您设法以某种方式传递函数类型并希望在内部调用它,那么您会遇到与将它们存储在函数指针或对象内部std::function相同的问题:即调用您需要两者,还需要成员函数作为具体对象。仅传递函数是不够的。

\n\n

但事实上你可以实现你想要的。只需将函数绑定到您的对象并随后传递它即可:

\n\n
template<typename T, typename F>\nvoid call(T&& t, F&&f)\n{\n    f(std::forward<T>(t));\n}\n\nstruct A\n{\n    void foo() { std::cout<<"hello"<<std::endl; }  \n};\n\nint main()\n{\n    A a;\n    auto f=std::bind(&A::foo, a);   //or possibly "std::ref(a)" instead of "a"\n    call(3,f);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

演示版

\n