出于实际原因,我有一个像
这样的课程template <class A>
class CRTP
{
template <int (A::*Member)()>
int func(void * obj)
{
int result
// Do something with Member, like
// result = (reinterpret_cast<A*>(obj)->*Member)();
return result;
}
};
template <void (A::*Member)()>
是一项要求,不能作为参数传递。
我还有一个班级基地
class Base : public CRTP<Base>
{
int aMemberOfBase() {...}
};
它的派生我想继承CRTP
class Derived : public CRTP<Derived>, public Base
{
int aMemberOfDerived() {...}
};
在Derived的某些成员中,我会做类似
的事情func<&Derived::aMemberOfDerived>(this);
func<&Base::aMemberOfBase>(this);
这可能吗?
(好吧,VC ++只编译第一行,不想读第二行......但Derived应该有成员
template <int (Base::*Member)()> int func(void * obj);
template <int (Derived::*Member)()> int func(void * obj);
我承认,这看起来很奇怪。但是下面的一段代码
template <void (Base::*Member)()> int func() {return 0;}
template <void (Derived::*Member)()> int func() {return 1;}
编译并返回func<&Base::someMember>() != func<&Derived::someMember>()
,因为模板的签名不一样且不能相同。)
我必须承认,我不能很好地评价标准所说的内容。但是我试图允许的继承模式是什么?如果是,为什么其中一行不能编译?
此外,如果我宣布
class Derived : public Base, public CRTP<Derived>
而不是
class Derived : public CRTP<Derived>, public Base
我得到编译时错误(在所有func<...>(...)
上),这意味着某处出现了错误。
另一方面,我知道
template <class A, int (A::*Member)()> int func(void * obj)
会删除CRTP的需要,但编写func<Derived, &Derived::aMember>()
会很痛苦。有没有像
template <class Class, void (Class::*Member)()> class A
{
void func(void * obj) {...(reinterpret_cast<Class*>(obj)->*Member)();...}
};
template <typename Signature> class B;
template <typename Class, typename Member>
class B<&Class::Member> : public class A<Class, &Class::Member> {};
允许B<&Base::Derived>().func(somePtrToBase)
?
答案 0 :(得分:1)
您可以通过限定基本成员模板的名称来消除歧义。以下应该有效:
template <typename A> struct CRTP
{
template <int (A::*Member)()> int func();
};
struct Base : CRTP<Base>
{
int aMemberOfBase();
};
struct Derived : CRTP<Derived>, Base
{
int aMemberOfDerived();
void foo()
{
CRTP<Derived>::func<&Derived::aMemberOfDerived>();
CRTP<Base>::func<&Base::aMemberOfBase>();
}
};
我公开了一切,以避免陷入访问控制细节。