2010-01-26 9 views
5

मैं उपरोक्त कन्स्ट्रक्टर के साथ प्रकार फू प्रकार की ऑब्जेक्ट को कैसे चालू नहीं कर सकता?सी ++ टेम्पलेटेड कन्स्ट्रक्टर संकलित नहीं करेगा

मेरे पास एक कक्षा बार है जो एक आंतरिक टाइपिफ़ ("टेम्पलेट टाइपपीफ" के लिए कामकाज के रूप में) का उपयोग करता है और इसे नीचे (कंस 1) के रूप में एक कन्स्ट्रक्टर में उपयोग करने का इरादा रखता है। हालांकि, मुझे संकलन करने के लिए प्रतीत नहीं होता है। क्या यह कानूनी सी ++ है? CASE 2 का सुझाव है कि समस्या बार में टाइपपीफ से संबंधित है।

मैं एक कन्स्ट्रक्टर को कैसे परिभाषित कर सकता हूं जो बार में टाइप के साथ ऑब्जेक्ट्स के std :: vectors स्वीकार करेगा?

#include <vector> 
#include <iostream> 
#include <utility> 

template <typename T> 
struct Bar 
{ 
    typedef std::pair<T, T> type; // or anything else that uses T 
}; 

struct Foo 
{ 
    Foo() {} 

    // CASE 1: doesn't compile 
    template <typename T> explicit Foo(const std::vector<typename Bar<T>::type>& data) 
    { 
     std::cout << "Hello\n"; 
    } 

    //// CASE 2: compiles, but it's not what I want 
    //template <typename T> explicit Foo(const std::vector<Bar<T> >& data) 
    //{ 
    // std::cout << "Hello\n"; 
    //} 
}; 

int main() 
{ 
    std::vector<Bar<int>::type> v; // for CASE 1 
    //std::vector<Bar<int> > v; // for CASE 2 

    Foo f(v); 
    return 0; 
} 
+0

क्या आप त्रुटि आउटपुट पोस्ट कर सकते हैं? –

+0

कुलपति ++ प्रतिलिपि निर्माता के साथ अपने निर्माता confuses और लिखते हैं: 'फू :: फू (स्थिरांक फू और)': 'स्थिरांक फू और' जीसीसी आउटपुट से 'std :: वेक्टर <_Ty>' से पैरामीटर 1 परिवर्तित नहीं कर सकते: 'Foo :: Foo (std :: vector > &)' – kmhofmann

+1

इंटेल सी ++ कंपाइलर कन्स्ट्रक्टर घोषणा के साथ लाइन पर निम्न, सहायक चेतावनी देता है: चेतावनी # 488 पर कॉल करने के लिए कोई मिलान करने वाला फ़ंक्शन नहीं : टेम्पलेट पैरामीटर "' T' "का उपयोग पैरामीटर टेम्पलेट के पैरामीटर प्रकारों को घोषित करने में नहीं किया जाता है" 'Foo :: Foo (const std :: vector :: प्रकार, std :: आवंटक :: प्रकार >> &)' " –

उत्तर

9

सी ++ मानक के पैरा 14.8.2.1, जब टेम्पलेट पैरामीटर एक गैर निष्कर्ष निकाला संदर्भ में केवल प्रयोग किया जाता है के अनुसार, इसी टेम्पलेट तर्क निष्कर्ष निकाला नहीं जा सकता:

तो एक टेम्पलेट पैरामीटर फ़ंक्शन टेम्पलेट के किसी फ़ंक्शन पैरामीटर में उपयोग नहीं किया जाता है, या केवल एक गैर-कटौती संदर्भ में उपयोग किया जाता है, इसके संबंधित टेम्पलेट-तर्क फ़ंक्शन कॉल से नहीं लिया जा सकता है और टेम्पलेट-तर्क स्पष्ट रूप से निर्दिष्ट होना चाहिए ।

nondeduced संदर्भों की परिभाषा, के रूप में §14.8.2.4 में कहा गया है:

nondeduced संदर्भों हैं: एक प्रकार की

  • नेस्टेड-नाम-विनिर्देशक कि योग्य-आईडी का उपयोग करके निर्दिष्ट किया गया था।

  • एक प्रकार है जो एक या टेम्पलेट तर्क के और अधिक में एक टेम्पलेट आईडी है कि एक अभिव्यक्ति का संदर्भ देता है एक टेम्पलेट पैरामीटर है।

Bar<T>::type में, Bar<T> एक नेस्टेड-नाम-विनिर्देशक और इसलिए एक गैर निष्कर्ष निकाला संदर्भ है, तो आप स्पष्ट रूप से (टेम्पलेट तर्क जब निर्माता ... जो संभव नहीं है बुला निर्दिष्ट करना होगा यानी आप Foo f<int>(v) नहीं लिख सकते हैं)।

मुझे लगता है संकलक टेम्पलेट तर्क अनुमान नहीं कर सकते क्योंकि यह है कि कम से कम बोझिल है, और अधिक शायद असंभव हो जाएगा: कल्पना बार विशेष है:

template<typename T> 
struct Bar 
{ 
    typedef std::pair<T,T> type; 
}; 

template<> 
struct Bar<char> 
{ 
    typedef std::pair<int,int> type; 
}; 

अब मैं एक अस्पष्टता जब std::vector<std::pair<int,int> > साथ फू के निर्माता बुला है: टेम्पलेट तर्क int या char होना चाहिए? और यहां तक ​​कि अगर ऐसी कोई अस्पष्टता नहीं थी, तो आप आसानी से देख सकते हैं कि कंपाइलर को सही टाइपिफ़ के साथ तत्कालता खोजने से पहले संभावित रूप से किसी भी प्रकार के साथ बार को तुरंत चालू करना होगा (ठीक है, मुझे यकीन नहीं है कि ऊपर दिए गए बयान वास्तव में प्रासंगिक हैं क्योंकि मैं अक्सर मैंने विचार किया है कि तुलना में अधिक स्मार्ट होने के लिए कंपाइलर्स को ढूंढें :-)!)

+0

आप 14.8.2.4/4 भी उद्धृत कर सकते हैं, जो दो नॉनडेड किए गए संदर्भों का नाम देता है। –

+0

सूचक के लिए धन्यवाद, मैंने जानकारी जोड़ा। –

4

आपका निर्माता है:

template <typename T> 
explicit 
Foo(const std::vector<typename Bar<T>::type>& data) 

टेम्पलेट तर्क T समारोह तर्क इस तरह से निष्कर्ष निकाला नहीं जा सकता है। (मुझे लगता है कि इसे "गैर-deducible संदर्भ" कहा जाता है, लेकिन मुझे यकीन नहीं है।)

यह बस काम नहीं करेगा। इसके बजाय आप

template <typename B> 
explicit 
Foo(const std::vector<B>& data) 

लिखने और कहने देगी कि B प्रकार typename Bar<T>::type की है अन्य तरीके खोजने के लिए होगा।

+0

आह, ल्यूक ने कृपया मेरे अस्पष्ट sta को अध्याय और कविता प्रदान की है tement: http://stackoverflow.com/questions/2140025/c-templated-constructor-wont-compile/2140182#2140182 – sbi

0

मुझे लगता है कि इसका एकमात्र कारण यह है कि आप "हैलो" प्रिंट करने के बजाय संबंधित प्रकार के बार को तुरंत चालू करना चाहते हैं।

शायद आप उलट दिशा (उलट कटौती है कि आप उम्मीद कर रहे हैं संकलक प्रदर्शन करने में सक्षम हो जाएगा की तरह) में प्रकार मानचित्रण की कोशिश कर सकते:

#include <utility> 
#include <vector> 

template <class T> 
struct BarType; 

template <class T> 
struct BarType<std::pair<T, T> > 
{ 
    typedef T type; 
}; 

template <class T> 
struct Bar {}; 

struct Foo 
{ 
    template <class T> 
    Foo(const std::vector<T>&) 
    { 
     Bar<typename BarType<T>::type> bar; 
     //... 
    } 
}; 

int main() 
{ 
    Foo(std::vector<std::pair<int, int> >()); 
} 
0

सकता है आप के लिए यह काम की तरह कुछ?

#include <vector> 
#include <iostream> 
#include <utility> 
#include <boost/static_assert.hpp> 

template <typename T> 
struct Bar 
{ 
    typedef std::pair<T, T> type; // or anything else that uses T 
    enum {val = 42}; 
}; 

template <typename T> 
struct Traits 
{ 
    enum {allowed = false}; 
}; 

template <typename T> 
struct Traits<std::pair<T, T> > 
{ 
    enum {allowed = true}; 
    typedef Bar<T> BarType; 
}; 

struct Foo 
{ 
    Foo() {} 

    template <typename T> explicit Foo(const std::vector<T>& data) 
    { 
     BOOST_STATIC_ASSERT(Traits<T>::allowed); 
     typedef typename Traits<T>::BarType BarType; 
     std::cout << BarType::val << std::endl; 
    } 
}; 

int main() 
{ 
    std::vector<Bar<int>::type> v; 
    std::vector<float> v2; 

    Foo f(v); 
// Foo f2(v2); // Compile error 
    return 0; 
} 

यह संकलित करता है और जीसीसी 4.4.1 पर चलता है। आप अन्य vector::value_type के लिए Traits विशेषज्ञ कर सकते हैं जो आपके कन्स्ट्रक्टर द्वारा अनुमत हैं।