1

出于实际原因,我有一个像

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)()>是一个要求,它不能作为参数传递。

而且我还有一个类 Base

class Base : public CRTP<Base>
{
    int aMemberOfBase() {...}
};

及其派生的,我也想继承 CRTP

class Derived : public CRTP<Derived>, public Base
{
    int aMemberOfDerived() {...}
};

在派生的一些成员中,我会做类似的事情

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)

4

1 回答 1

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>();
    }
};

我公开了所有内容,以避免陷入访问控制细节。

于 2013-03-09T22:46:04.180 回答