2010-12-18 83 views
12

我希望派生类是模板类的后代。该类取决于后代的成员。 总之我想这个代码编译:使用派生类'typedef的基地

struct IBootParams 
{ 
    virtual bool GetImmediate() = 0; 
}; 

template <class T> 
struct TBootBootParams 
{ 
    typename T::TransType transferType; 

    typename T::UseAbort_ useAbort; 

    bool GetImmediate() 
    { 
     if (transferType == T::e1) 
     { 
      return useAbort.someFlag; 
     } 

     return false; 
    } 

}; 

struct BootBootParams : public TBootBootParams<BootBootParams> 
{ 
    enum SomeEnum 
    { 
     e1=0, 
     e2, 
     e3 
    }; 

    struct UseAbort 
    { 
     bool  someFlag;   

     char  someMember;    
     int   otherMember;   
    } useAbort; 

    typedef SomeEnum TransType; 
    typedef UseAbort UseAbort_; 
}; 

struct BootAltBootParams : public TBootBootParams<BootAltBootParams> 
{ 
    enum SomeEnum 
    { 
     e1=5, 
     e2, 
     e3 
    }; 

    struct UseAbort 
    { 
     bool  someFlag;   

     long long  someMember;    
     long long  otherMember;   
    } useAbort; 

    typedef SomeEnum TransType; 
    typedef UseAbort UseAbort_; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    BootBootParams bp; 
    BootAltBootParams bpa; 

    bool f = bp.GetImmediate(); 
    f = bpa.GetImmediate(); 
} 
+0

那么错误是什么? – ybungalobill 2010-12-18 20:04:41

+2

你为什么要声明IBootParams? – 2010-12-18 20:06:26

回答

10

你不能这样做。当编译器实例化TBootBootParams<BootBootParams>时,它尚未完全读取BootBootParams的整个定义,因此您无法从TBootBootParams定义内部访问其成员(TBootBootParams的成员函数是一个例外,因为它们在稍后实例化)。

通常的解决办法是有一个traits类:

template<class T> struct TBootBootParams_traits; 

template <class T> 
struct TBootBootParams 
{ 
    typename TBootBootParams_traits<T>::TransType transferType; 

    typename TBootBootParams_traits<T>::UseAbort_ useAbort; 

    bool GetImmediate() 
    { 
     if (transferType == TBootBootParams_traits<T>::e1) 
     { 
      return useAbort.someFlag; 
     } 

     return false; 
    } 

}; 

struct BootBootParams; 
template<> struct TBootBootParams_traits<BootBootParams> 
{ 
    enum SomeEnum 
    { 
     e1=5, 
     e2, 
     e3 
    }; 

    struct UseAbort 
    { 
     bool  someFlag;   

     long long  someMember;    
     long long  otherMember;   
    }; 

    typedef SomeEnum TransType; 
    typedef UseAbort UseAbort_; 
}; 

struct BootBootParams : 
    public TBootBootParams<BootBootParams>, 
    public TBootBootParams_traits<BootBootParams> 
{ 
    UseAbort_ useAbort; 
}; 
+0

这比我认为的更好。有点干净。 – Omnifarious 2010-12-18 20:23:23

+0

看起来真棒。我只是不明白为什么'template <> struct TBootBootParams_traits'声明在其前向声明中没有'<>'中的任何类型参数。 – 2010-12-18 20:24:47

+1

@Sergey:因为它是专业化的。 @All + @Omnifarious:这是将某些参数传递给某个模板的规范方法。例如。 STL将它用于迭代器(iterator_traits)。 – ybungalobill 2010-12-18 20:26:45

4

没有办法,这可以工作,是不是一个黑客攻击的一位。所以这是我尝试在一个黑客攻击的一位:

struct IBootParams 
{ 
    virtual bool GetImmediate() = 0; 
}; 

template <class T> 
struct TBootBootParams : public IBootParams 
{ 
    typename T::TransType transferType; 

    typename T::UseAbort_ useAbort; 

    virtual bool GetImmediate() 
    { 
     if (transferType == T::e1) 
     { 
      return useAbort.someFlag; 
     } 

     return false; 
    } 

}; 

struct BootBootParams_types 
{ 
    enum SomeEnum 
    { 
     e1=0, 
     e2, 
     e3 
    }; 

    struct UseAbort 
    { 
     bool  someFlag; 

     char  someMember; 
     int   otherMember; 
    } useAbort; 

    typedef SomeEnum TransType; 
    typedef UseAbort UseAbort_; 
}; 

struct BootBootParams : public BootBootParams_types, 
         public TBootBootParams<BootBootParams_types> 
{ 
}; 

struct BootAltBootParams_types 
{ 
    enum SomeEnum 
    { 
     e1=5, 
     e2, 
     e3 
    }; 

    struct UseAbort 
    { 
     bool  someFlag; 

     long long  someMember; 
     long long  otherMember; 
    } useAbort; 

    typedef SomeEnum TransType; 
    typedef UseAbort UseAbort_; 
}; 

struct BootAltBootParams : public BootAltBootParams_types, 
          public TBootBootParams<BootAltBootParams_types> 
{ 
}; 

int main(int argc, const char * argv[]) 
{ 
    BootBootParams bp; 
    BootAltBootParams bpa; 

    bool f = bp.GetImmediate(); 
    f = bpa.GetImmediate(); 
} 
+1

+1因为您近距离:) – ybungalobill 2010-12-18 20:34:10

+1

谢谢。有趣! – Romeno 2010-12-20 10:57:40

0

对于这种方法的工作,你必须包括模板类对象作为父类中的一员。

2

这是不是你想要做什么? It compiles.

struct IBootParams 
{ 
    virtual bool GetImmediate() = 0; 
}; 

template <class T> 
struct TBootBootParams 
{ 
    bool GetImmediate() 
    { 
     if (static_cast<T*>(this)->transferType == T::e1) 
     { 
      return static_cast<T*>(this)->useAbort.someFlag; 
     } 

     return false; 
    } 

}; 

struct BootBootParams : public TBootBootParams<BootBootParams> 
{ 
    enum SomeEnum 
    { 
     e1=0, 
     e2, 
     e3 
    } transferType; 

    struct UseAbort 
    { 
     bool  someFlag;   

     char  someMember;    
     int   otherMember;   
    } useAbort; 
}; 

struct BootAltBootParams : public TBootBootParams<BootAltBootParams> 
{ 
    enum SomeEnum 
    { 
     e1=5, 
     e2, 
     e3 
    } transferType; 

    struct UseAbort 
    { 
     bool  someFlag;   

     long long  someMember;    
     long long  otherMember;   
    } useAbort; 
}; 

int main(void) 
{ 
    BootBootParams bp; 
    BootAltBootParams bpa; 

    bool f = bp.GetImmediate(); 
    f = bpa.GetImmediate(); 
} 
+0

哇。编译真的令我印象深刻。它应该编译?只是因为它的实际运作并不意味着它应该。 :-) – Omnifarious 2010-12-18 20:22:42

+0

顺便说一下,它也编译在gcc 4.5上。 – Omnifarious 2010-12-18 20:32:41

+0

@Omnifarious:是的,这应该编译,它是直接的CRTP。我摆脱了导致问题的基类成员......因为他们的数据类型是由派生类型决定的,所以他们可以在派生类型中声明,并且基类可以通过利用模板参数很好地访问它们。 – 2010-12-18 20:36:38

1

我想有点变化ybungalobill的解决方案计算自己的需要。这是我得到的

template<class T> 
struct TBootBootParams_traits; 

template <class T> 
struct TBootBootParams 
{ 
    typedef TBootBootParams_traits<T> Traits; 

    typename Traits::TransType transferType; 
    typename Traits::UseAbort_ useAbort; 

    bool GetImmediate() 
    { 
     if (transferType == TBootBootParams_traits<T>::e1) 
     { 
      return useAbort.someFlag; 
     } 

     return false; 
    } 
}; 

struct BootBootParams; 
struct BootAltBootParams; 

template<> 
struct TBootBootParams_traits<BootBootParams> 
{ 
    enum SomeEnum 
    { 
     e1=5, 
     e2, 
     e3 
    }; 

    struct UseAbort 
    { 
     bool  someFlag;   

     long long  someMember;    
     long long  otherMember;   
    }; 

    typedef SomeEnum TransType; 
    typedef UseAbort UseAbort_; 
}; 

template<> 
struct TBootBootParams_traits<BootAltBootParams> 
{ 
    enum SomeEnum 
    { 
     e1=5, 
     e2, 
     e3 
    }; 

    struct UseAbort 
    { 
     bool  someFlag;   

     int someMember;    
     float otherMember;   
    }; 

    typedef SomeEnum TransType; 
    typedef UseAbort UseAbort_; 
}; 

struct BootBootParams : 
    public TBootBootParams<BootBootParams> 
{ 

}; 

struct BootAltBootParams : 
    public TBootBootParams<BootAltBootParams> 
{ 

}; 

int main(void) 
{ 
    BootBootParams bp; 
    BootAltBootParams bpa; 

    bool f = bp.GetImmediate(); 
    f = bpa.GetImmediate(); 
} 

总结。我使用模板类作为另一个类的这个类将所有类型的数据有一个必须具备的选项。这正是我需要的。再次感谢您的选择!