2012-05-19 12 views
47

counter एक intstd :: to_string - अतिभारित समारोह के कहने से ज्यादा तर्क सूची

void SentryManager::add(std::string name,std::shared_ptr<Sentry>){ 
    name = name + std::to_string(counter); 
} 

है इस त्रुटि को रोकने के लिए सबसे अच्छा तरीका है क्या से मेल खाता है? जब मैं आलसी था तो मैंने int long long (या कुछ) बनाया, लेकिन मुझे यकीन है कि इसे हल करने का एक बेहतर तरीका है।

त्रुटि संदेश:

sentrymanager.cpp(8): error C2668: 'std::to_string' : ambiguous call to overloaded function 

मैं विज़ुअल सी ++ उपयोग कर रहा हूँ 2010 एक्सप्रेस।

+0

क्या आप वास्तविक त्रुटि संदेश, और आप किस कंपाइलर और संस्करण का उपयोग कर रहे हैं (जीसीसी 4.5 के साथ पुन: उत्पन्न नहीं) शामिल कर सकते हैं। – Mat

+0

ठीक है - संपादन देखें। – pighead10

उत्तर

79

कुलपति में ++ 2010 वहाँ std::to_string के तीन भार के कि क्रमशः ले long long, unsigned long long, और long double, कर रहे हैं - स्पष्ट रूप से int इनमें से कोई भी है, और कोई भी रूपांतरण एक और (demo) की तुलना में बेहतर है, इसलिए रूपांतरण परोक्ष नहीं किया जा सकता/स्पष्ट रूप से। सी ++ 11 मानक ही वास्तव में std::to_string की नौ भार के ([string.conversions] के लिए कहता है -

असली सी ++ 11 सहायता के संदर्भ में, इस कुलपति ++ 2010 के मानक पुस्तकालय कार्यान्वयन की ओर से एक असफल है/7):

string to_string(int val); 
string to_string(unsigned val); 
string to_string(long val); 
string to_string(unsigned long val); 
string to_string(long long val); 
string to_string(unsigned long long val); 
string to_string(float val); 
string to_string(double val); 
string to_string(long double val); 

इन भार के उपस्थित के सभी था, तो आप स्पष्ट रूप से यह समस्या नहीं होगी; हालांकि, वीसी ++ 2010 वास्तविक सी ++ 11 मानक (जो इसकी रिलीज के समय अभी तक मौजूद नहीं था) पर आधारित नहीं था, बल्कि N3000 (से) पर आधारित है, जो इन अतिरिक्त के लिए कॉल करता है भार के। नतीजतन, यह इसके लिए जिम्मेदार कठोर है कुलपति ++ भी ज्यादा यहाँ ...

किसी भी मामले में, केवल कॉल के एक मुट्ठी भर के लिए, वहाँ अस्पष्टता अपने आप को हल करने के लिए एक डाली उपयोग करने के साथ कुछ भी गलत नहीं:

void SentryManager::add(std::string& name, std::shared_ptr<Sentry>) { 
    name += std::to_string(static_cast<long long>(counter)); 
} 

या फिर, आपकी codebase में std::to_string के अत्यधिक उपयोग अगर, कुछ रैपर लिख सकते हैं और उन के बजाय का उपयोग करें - इस तरह से, कोई कॉल-साइट कास्टिंग की जरूरत है:

#include <type_traits> 
#include <string> 

template<typename T> 
inline 
typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, std::string>::type 
to_string(T const val) { 
    return std::to_string(static_cast<long long>(val)); 
} 

template<typename T> 
inline 
typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, std::string>::type 
to_string(T const val) { 
    return std::to_string(static_cast<unsigned long long>(val)); 
} 

template<typename T> 
inline typename std::enable_if<std::is_floating_point<T>::value, std::string>::type 
to_string(T const val) { 
    return std::to_string(static_cast<long double>(val)); 
} 

// ... 

void SentryManager::add(std::string& name, std::shared_ptr<Sentry>) { 
    name += to_string(counter); 
} 

मैं यह जांच नहीं सकता कि वीसी ++ 2010 एसएफआईएनएई के उपर्युक्त उपयोग के साथ सफल होता है या विफल रहता है; अगर यह विफल रहता है, निम्नलिखित - SFINAE के बजाय टैग प्रेषण का उपयोग कर - compilable (यदि संभवतः कम स्पष्ट) होना चाहिए:

#include <type_traits> 
#include <string> 

namespace detail { 
    template<typename T>     // is_float   is_unsigned 
    inline std::string to_string(T const val, std::false_type, std::false_type) { 
     return std::to_string(static_cast<long long>(val)); 
    } 

    template<typename T>     // is_float   is_unsigned 
    inline std::string to_string(T const val, std::false_type, std::true_type) { 
     return std::to_string(static_cast<unsigned long long>(val)); 
    } 

    template<typename T, typename _>  // is_float 
    inline std::string to_string(T const val, std::true_type, _) { 
     return std::to_string(static_cast<long double>(val)); 
    } 
} 

template<typename T> 
inline std::string to_string(T const val) { 
    return detail::to_string(val, std::is_floating_point<T>(), std::is_unsigned<T>()); 
} 
+3

सभी अधिभार विजुअल सी ++ 11 बीटा में मौजूद हैं। यह वास्तव में मानक लाइब्रेरी कार्यान्वयन में विफल नहीं है: कुछ ओवरलोड को C++ 11 _after_ विज़ुअल सी ++ 2010 में रिलीज़ किया गया था। –

+0

@ जेम्स: ठीक है, इसे प्रतिबिंबित करने के लिए संपादित किया गया। – ildjarn

+1

दोष रिपोर्ट 1261 200 9 में हुई; मुझे लगता है कि कम से कम धीरे-धीरे आगे बढ़ने के लिए माइक्रोसॉफ्ट को * थोड़ा * दोष देना उचित है। – zwol

9

आप C++ DR 1261 पर फिसल गया है, जो भाग में पढ़ता

कोड " int i; to_string(i); "संकलित करने में विफल रहता है, 'int' 'long long' और 'long long unsigned' के बीच संदिग्ध है। यह उपयोगकर्ताओं को to_string का उपयोग करने के लिए बड़ी संख्या में संख्याओं को कास्ट करने की उम्मीद करने के लिए अनुचित लगता है।

प्रस्तावित संकल्प अधिक अधिभार जोड़ने के लिए है।GCC has implemented this already; मुझे लगता है कि एमएसवीसी नहीं है।

+4

संकल्प अंतिम सी ++ 11 मानक में शामिल किया गया था। विजुअल सी ++ 11 बीटा में सभी ओवरलोड शामिल हैं। –

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