【发布时间】:2015-09-04 23:26:33
【问题描述】:
为什么成员函数不能用作模板参数? 例如,我想做这样的事情:
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;
}
我知道可以使用指向成员的指针来完成类似的事情; 好吧,大多数时候它已经足够酷了,但我只是好奇为什么“应该”使用指针。
我认为解释上面的“p->func()”没有歧义。 为什么标准禁止我们使用成员函数作为模板参数? 根据我的编译器(VC++ 2013),即使是静态成员函数也是不允许的。有谁知道原因?或者,有没有办法在不因指针取消引用而损失任何性能的情况下做同样的事情?
谢谢。
【问题讨论】:
-
您看不到任何歧义,因为您认为模板就像宏,但事实并非如此,类型安全是由编译器实现的,您的表达式
p->func()在编译时没有意义,而Foo::Bar是不是void(&func)()类型,而是void(TOwner::*func)()。 -
@Jean-BaptisteYunès 嗯,Foo::Bar 不是 void(TOwner::*func)() 类型,它是 &Foo::Bar 的类型。我写 void(&func)() 的原因是我能想到的最好的东西是 Foo::Bar; 的类型。实际上,根据我的编译器, decltype(Foo::Bar) 的结果是 void(void) 。我要问的是在允许上述情况时可能会破坏类型安全。谢谢。
-
可以作为参考。我只是想指出问题在于:类型(参数和返回类型是什么)和签名之间存在一些区别? (上下文/命名空间+类型)。唉 Foo::Bar 签名不是 void(void)。
-
重点是:Foo::Bar 是一个函数成员,而你的模板 arg 是一个函数,但你将它用作函数成员。
-
@Jean-BaptisteYunès 是的,我的意思是,不幸的是,既没有“成员函数类型”也没有“对成员类型的引用”,这就是我写上面这样的原因。
标签: c++ templates member-functions