2010-11-28 15 views
6

मैं वर्तमान में एक सामान्य वेक्टर टेम्पलेट वर्ग (ज्यामितीय इकाई, कंटेनर नहीं) के बाद हस्ताक्षर के साथ लिख रहा हूँ ...किसी विशिष्ट स्थिति को पूरा होने पर C++ टेम्पलेट क्लास विधि के तत्कालता को कैसे रोकें?


template< typename T, unsigned N > 
class vector 
{...} 

... जहां टी अंकगणितीय प्रकार और एन, आयाम है। मैं ऑपरेटर^(वर्ग परिभाषा के अंदर स्थित) की एक अधिभार के रूप में पार उत्पाद को परिभाषित करने और इसे सक्षम करने के केवल जब एन == 3. मैं अब है चाहते हैं:


typename boost::lazy_enable_if_c< (N == 3), vector >::type 
inline operator ^(const vector &rhs) const 
{ 
    vector ret; 
    ret(0) = val_[1] * rhs(2) - val_[2] * rhs(1); 
    ret(1) = val_[2] * rhs(0) - val_[0] * rhs(2); 
    ret(2) = val_[0] * rhs(1) - val_[1] * rhs(0); 
    return ret; 
} 

दुर्भाग्य से, इस टेम्पलेट instantiating !


error: no type named ‘type’ in ‘struct boost::lazy_enable_if_c < false, flare::math::vector < flare::math::fixed < short int, 8u >, 2u > >’ 

क्या मैं गलत कर रहा हूँ: एन के साथ = 3, भले ही ऑपरेटर^संदर्भित नहीं है, तो निम्न त्रुटि पैदावार? ऐसे मामले में boost :: enable_if को बढ़ावा देने का कोई विकल्प है?

बहुत बहुत धन्यवाद।

उत्तर

4

त्रुटि संदेश के समीपस्थ कारण यह है कि, the docs के अनुसार, "lazy_enable_if का दूसरा तर्क एक वर्ग प्रकार है कि एक नेस्टेड प्रकार type नामित जब भी पहले पैरामीटर (हालत) सच है परिभाषित करता है होना चाहिए।" है यह स्पष्ट रूप से यहां संतुष्ट नहीं है (जब तक कि आपके vector प्रकार में typedef something type; शामिल न हो)।

आपको lazy_... की आवश्यकता नहीं है। दस्तावेज़ों के मुताबिक, केवल तभी जरूरी है जब दूसरा तर्क अपरिभाषित किया जा सके (उदाहरण के लिए यदि दूसरा तर्क typename foo<T>::bar था, और bar प्रकार सभी प्रकार T के लिए परिभाषित नहीं किया गया है)। vector (जिसका अर्थ है vector<T, N>) हमेशा परिभाषित किया जाएगा।

तो निश्चित रूप से हो रही lazy_ से छुटकारा कोशिश, या वैकल्पिक रूप एक do-कुछ भी नहीं वर्ग template <typename T> struct nop { typedef T type; }; लक्षण बना सकते हैं और nop<vector> साथ lazy_enable_if_c को 2 आर्ग की जगह। लेकिन मेरा अनुमान है कि आप पहले से ही कम से कम पूर्व की कोशिश कर चुके हैं। :)

और अब मैं देखता हूं कि यह क्यों काम नहीं करेगा। मानक 14.7.1/1 के अनुसार:

Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3), the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program. The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions or default arguments, of the class member functions, member classes, static data members and member templates;

तो कुछ भी है कि वर्ग सभी तरीकों के लिए घोषणाओं का दृष्टांत को, जो जब N != 3 असफल हो जायेगी कोशिश करेंगे instantiated जा करने के लिए कारण बनता है। तो ऐसा लगता है कि आपको हमेशा एक मौजूदा विधि का उपयोग करने की आवश्यकता होगी जो इसके बजाय फ़ंक्शन टेम्पलेट पर हाथ रखे। चिंता मत करो, किसी भी सभ्य संकलक अभी भी इस के माध्यम से इनलाइन में सक्षम हो जाएगा:

template< typename T, unsigned N > class vector; // Fwd decl. 

template< typename T, unsigned N > 
inline boost::enable_if_c< (N == 3), vector<T, N> >::type 
magic(const vector<T, N>& lhs, const vector<T, N>& rhs) { 
    /* Do the calculation as before... */ 
    return ret; 
} 

template< typename T, unsigned N > 
class vector { 
    ... 
    inline vector operator ^(const vector &rhs) const { 
     return magic(*this, rhs); 
    } 
}; 

यह काम करेंगे क्योंकि सदस्य समारोह परिभाषाओं instantiated नहीं कर रहे हैं जब तक कि वे वास्तव में कहा जाता है (या उनके पते लिया जाता है आदि)।

+0

सबसे पहले, गहराई से स्पष्टीकरण के लिए आपको बहुत बहुत धन्यवाद।दरअसल, मेरे पास टाइपिफ़ वेक्टर प्रकार था; मेरी कक्षा परिभाषा के अंदर, लेकिन मैं इस महत्वपूर्ण विवरण का उल्लेख करना भूल गया। यही कारण है कि मुझे समझ में नहीं आया कि क्यों जीसीसी इस त्रुटि को फेंक रहा था :: प्रकार परिभाषित नहीं किया जा रहा है। इसके अलावा, मैंने enable_if के lazy_ संस्करण के उद्देश्य को गलत समझा। आपकी व्याख्या ने मुझे इसे समझने में मदद की। इसके प्रकाश में, मैं बस ऑपरेटर के बाहरी संस्करण में बदल गया^और यह अपेक्षित के रूप में काम किया। त्रुटि संदेश उत्पन्न हुआ जब N! = 3 थोड़ा सा गूढ़ है, लेकिन इसका सामना किया जा सकता है। पुनः आपका बहुत - बहुत धन्यवाद! – pmjobin

+0

@pmjobin: आपका स्वागत है :) हाँ, टेम्पलेट त्रुटि संदेश भयानक हैं ... –

2

मुझे विश्वास है कि आपकी समस्या "कक्षा परिभाषा के अंदर स्थित है"। मुझे लगता है कि अगर आप एक विधि के माध्यम से एक समारोह के माध्यम से ऑपरेटर अधिभार लोड करते हैं तो आपको कम परेशानी होगी।

मुझे लगता है कि एक समारोह में स्विच करने के बाद जादू को बढ़ाने के बजाए केवल सादे पुराने विशेषज्ञता के साथ मिलना संभव हो सकता है, लेकिन मुझे इसके बारे में कम यकीन नहीं है।

संबंधित मुद्दे