2011-11-17 5 views
15

int x = fromString("test"): 'ValueType'क्यों सी ++ असाइनमेंट से टेम्पलेट प्रकार को कम नहीं कर सकता?

int x = fromString<int>("test") के लिए टेम्पलेट तर्क अनुमान नहीं कर सकता: ठीक काम करता है के रूप में उम्मीद

तो क्यों यहाँ संकलक संघर्ष करता है? मैं इसे सभी प्रकार के वास्तविक टेम्पलेट कार्यों के साथ देखता हूं, न सिर्फ इस मूर्ख उदाहरण के लिए। यह भाषा की एक विशेषता होनी चाहिए, लेकिन क्या?

+10

कुछ है कि एक पूर्णांक "toString" कहा जाता है में बदल सकते हैं क्यों है? –

+2

[यह सवाल] (http: // stackoverflow।कॉम/प्रश्न/442026/फ़ंक्शन-ओवरलोडिंग-बाय-रिटर्न-टाइप) एक समान समस्या पर चर्चा करता है। –

+0

यह "बस नहीं करता"। ध्यान दें कि यह भाषा है, संकलक नहीं - हालांकि वास्तव में यह आंशिक रूप से भाषा में निर्दिष्ट नहीं है क्योंकि यह सामान्य मामले में सही होने के लिए कंपाइलर के लिए मुश्किल हो सकता है। –

उत्तर

12

सी ++ वापसी मूल्य पर प्रकार अनुमान नहीं करता है। यानी, तथ्य यह है कि इसे एक int को सौंपा जा रहा है टेम्पलेट पैरामीटर कटौती में उपयोग नहीं किया जाता है।

(निकाला गया संपादित करें, के बाद से किसी और ने पहले। अतिभारित डाली समाधान प्रदान किया गया)

+1

धन्यवाद। मैं इसे _need_ करने के लिए नहीं है, यह सिर्फ उन परेशान quirks में से एक है और मैं समझना चाहता था क्यों। –

1

ऐसा लगता है कि अपने टेम्पलेट की तरह टेम्प्लेट की वापसी प्रकार जो स्वचालित रूप से निष्कर्ष निकाला नहीं जा सकता है और इसी कारण आप यहाँ में इसे जोड़ने की आवश्यकता है।

+0

डिफर्ड रिटर्न टाइप घोषणा (या जिसे भी कहा जाता है) का एक अलग उद्देश्य है। यह आपको फ़ंक्शन के तर्कों के प्रकार के आधार पर रिटर्न प्रकार घोषित करने की अनुमति देता है। यह सिर्फ तब तक स्थगित कर देता है जब तक तर्क दायरे में न हो। यह कॉलर के उपयोग से परिणाम के प्रकार को कम करना संभव नहीं बनाता है। – visitor

+0

टिप्पणी के लिए धन्यवाद, मैं अपनी पोस्ट से हटा दूंगा :-) – Firedragon

0

एक उदाहरण के लिए बुरा विकल्प इसके अलावा (शायद समझ में नहीं बल्कि toString से int x = to<int>("1235") वाला राज्य बन गया), समस्या यह है कि वापसी प्रकार अधिभार संकल्प या प्रकार निष्कर्ष में भाग नहीं लेता है [1]। इस का कारण यह है कि अभिव्यक्ति कई स्थानों में इस्तेमाल किया जा सकता है, जहां वापसी के प्रकार निष्कर्ष निकाला नहीं किया जा सकता है:

// assuming template <typename T> T to(std::string): 
// 
f(to("123"));   // where there are two overloads f(int), f(double) 
int x = 1.5 * to("123"); // T == int? T == double? 
to("123");    // now what? returned object can be ignored! 

तो निर्णय है कि वापसी प्रकार अधिभार संकल्प या प्रकार कटौती में भाग नहीं लेंगे।

[1] नहीं है इस नियम है, जो एक से अधिक अधिभार, जहां अधिभार या तो गंतव्य सूचक या एक स्पष्ट कलाकारों द्वारा चयन किया जाना चाहिए के साथ एक समारोह सूचक के मूल्यांकन है के लिए एक एकल अपवाद है, लेकिन इस केवल एक अपवाद है और किसी अन्य संदर्भ में इसका उपयोग नहीं किया जाता है:

void f(); 
void f(int); 
void g(void (*)()); 
void g(void (*)(int)); 

void (*p1)() = &f;  // overload selected based on destination type 
void (*p2)(int) = &f; 
g((void (*)(int))&f); // overload selected based on explicit cast 
+0

"एक फ़ंक्शन पॉइंटर" - पॉइंटर-टू-सदस्य-फ़ंक्शन समेत। –

16

आप वापसी प्रकार के आधार पर कटौती नहीं कर सकते हैं। हालांकि, आप समान वाक्य रचना के साथ एक समाधान लागू कर सकते हैं, अतिभारित डाली ऑपरेटर का उपयोग:

#include <iostream> 
#include <sstream> 
#include <string> 
using namespace std; 

class FromString{ 
private: 
    string m_data; 
public: 
    FromString(const char*data) : m_data(data) {} 

    template<typename T> 
    operator T(){ 
     T t; 
     stringstream ss(m_data); 
     ss >> t; 
     return t; 
    } 

}; 

template<> FromString::operator bool(){ 
    return (m_data!="false"); //stupid example 
} 

int main(){ 

    int ans = FromString("42");  
    bool t = FromString("true"); 
    bool f = FromString("false"); 

    cout << ans << " " << t << " " << f << endl; 

    return 0; 
} 

आउटपुट:

42 1 0 
+0

सार्वभौमिक रूपांतरण समारोह, आउच! लेकिन चूंकि 'ऑपरेटर =' एक मित्र नहीं हो सकता है, मुझे लगता है कि यह सबसे अच्छा समाधान है, +1। – Potatoswatter

0

एक समारोह की वापसी प्रकार अधिभार संकल्प पर निर्भर है, नहीं दूसरी तरह के चारों ओर।/आरएचएस तर्क प्रकार, जब एक स्पष्ट operator= परिभाषित किया गया है को छोड़कर (चाहे स्टैंडअलोन के रूप में या एक सदस्य के रूप में कोई फर्क नहीं पड़ता) operator= आमतौर पर केवल बराबर एलएचएस लिए मौजूद है:

एक चाल है कि हालांकि काम करता है।

इस प्रकार, ओवरलोड रिज़ॉल्यूशन operator=(int &, int) मिलेगा, और देखें कि आपके फ़ंक्शन से वापसी मूल्य int में परिवर्तनीय है या नहीं। यदि आप एक अस्थायी लौटाते हैं जिसमें operator int है, तो यह एक स्वीकार्य रिज़ॉल्यूशन है (भले ही operator inttemplate<typename T> operator T के सामान्य रूप में है)।

इस प्रकार:

template<typename T, typename U> 
U convert_impl(T const &t); 

template<typename T> 
struct convert_result { 
    convert_result(T const &t) : t(t) { } 
    template<typename U> operator U(void) const { return convert_impl<U>(t); } 
    T const &t; 
}; 

template<typename T> 
convert_result<T> convert(T const &t) { return t; } 
संबंधित मुद्दे