2010-04-01 4 views
9

में सीआरटीपी के साथ पॉलिसी-आधारित डिज़ाइन मिलाकर मैं एक नीति-आधारित मेजबान वर्ग (यानी, एक वर्ग जो अपनी टेम्पलेट कक्षा से विरासत में आता है) लिखने का प्रयास कर रहा हूं, जहां एक मोड़ के साथ पॉलिसी क्लास भी टेम्पलेट है मेजबान वर्ग, ताकि वह अपने प्रकारों तक पहुंच सके। एक उदाहरण जहां यह उपयोगी हो सकता है, जहां एक पॉलिसी (वास्तव में मिश्रित की तरह प्रयोग की जाती है), मेजबान वर्ग को पॉलिमॉर्फिक क्लोन() विधि के साथ बढ़ाती है। यहाँ मैं क्या कर रहा हूँ का एक न्यूनतम उदाहरण है:सी ++

template <template <class> class P> 
struct Host : public P<Host<P> > { 
    typedef P<Host<P> > Base; 
    typedef Host* HostPtr; 
    Host(const Base& p) : Base(p) {} 
}; 

template <class H> 
struct Policy { 
    typedef typename H::HostPtr Hptr; 
    Hptr clone() const { 
    return Hptr(new H((Hptr)this)); 
    } 
}; 

Policy<Host<Policy> > p; 
Host<Policy> h(p); 

int main() { 
    return 0; 
} 

यह, दुर्भाग्य से, में संकलित करने के लिए, विफल रहता है क्या परिपत्र प्रकार निर्भरता की तरह मुझे लगता है:

try.cpp: In instantiation of ‘Host<Policy>’: 
try.cpp:10: instantiated from ‘Policy<Host<Policy> >’ 
try.cpp:16: instantiated from here 
try.cpp:2: error: invalid use of incomplete type ‘struct Policy<Host<Policy> >’ 
try.cpp:9: error: declaration of ‘struct Policy<Host<Policy> >’ 
try.cpp: In constructor ‘Host<P>::Host(const P<Host<P> >&) [with P = Policy]’: 
try.cpp:17: instantiated from here 
try.cpp:5: error: type ‘Policy<Host<Policy> >’ is not a direct base of ‘Host<Policy>’ 

किसी को भी एक पहचान सकते हैं तो स्पष्ट गलती, या सफलतापूर्वक नीतियों में सीआरटीपी मिश्रण है, मैं किसी भी मदद की सराहना करता हूं।

उत्तर

6

वास्तव में समस्या HostPtr घोषणा के कारण है जब तक कि आप पॉलिसी से प्राप्त नहीं होते हैं। सटीक अर्थशास्त्र के बारे में कुछ चर्चा है जहां ये घोषणाएं तत्काल टेम्पलेट्स द्वारा दिखाई देती हैं, जिनमें बहुत जटिल समस्याएं हैं, this defect report देखें।

लेकिन आपके मामले में, स्थिति स्पष्ट है: कक्षा निकाय से पहले, कोई भी कोड कक्षा के सदस्यों की कोई घोषणा नहीं देख सकता है, और इसलिए आपका कोड विफल हो जाता है।

template <template <class,class> class P> 
struct Host : public P<Host<P>, Host<P>* > { 
    typedef P<Host<P> > Base; 
    Host(const Base& p) : Base(p) {} 
}; 

template <class H, class Hptr> 
struct Policy { 
    typedef Hptr HostPtr; 
    HostPtr clone() const { 
    return Hptr(new H((Hptr)this)); 
    } 
}; 

अगर वहाँ अधिक प्रकार के होते हैं, तो आप एक विशेषता

template <class Host> 
struct HTraits { 
    typedef Host *HostPtr; 
    // ... 
}; 

template <template <class,class> class P> 
struct Host : public P<Host<P>, HTraits< Host<P> > > { 
    typedef P<Host<P> > Base; 
    Host(const Base& p) : Base(p) {} 
}; 

template <class H, class Htraits> 
struct Policy { 
    typedef typename Htraits::HostPtr HostPtr; 
    HostPtr clone() const { 
    return Hptr(new H((Hptr)this)); 
    } 
}; 
पारित करने के लिए तय कर सकते हैं आप एक टेम्पलेट तर्क के रूप में प्रकार गुजर सकता है