2011-06-26 11 views
19
void foo (const std::string &s) {} 

int main() { 
    foo(0); //compiles, but invariably causes runtime error 
    return 0; 
} 

संकलक (छ ++ 4.4) जाहिरा तौर पर 0char* NULL के रूप में व्याख्या, और string::string(const char*, const Allocator &a = Allocator()) फोन करके s निर्माण करती है। जो निश्चित रूप से बेकार है, क्योंकि NULL सूचक एक सी-स्ट्रिंग के लिए मान्य सूचक नहीं है। जब मैं foo(1) पर कॉल करने का प्रयास करता हूं, तो यह गलत व्याख्या तब उत्पन्न नहीं होती है, यह मददगार रूप से संकलन-समय त्रुटि उत्पन्न करती है।मैं `0` से निर्मित std :: स्ट्रिंग से उत्पन्न होने वाली परेशानी को कैसे रोकूं?

वहाँ संकलन समय पर इस तरह के कोई त्रुटि या चेतावनी प्राप्त करने के लिए जब मैं गलती से bar(0) साथ की तरह

void bar(const std::string &s, int i=1); 

एक समारोह फोन, string के बारे में भूल जाते हैं, और वास्तव में i=0 के लिए जिसका अर्थ है किसी भी संभावना है?

+3

पर कोई त्रुटि उत्पन्न नहीं करेगा वास्तव में संकलक से कुछ मदद के बिना नहीं। कुछ कार्यान्वयनों ने इस मामले को पकड़ने के लिए एक निजी 'मूल_स्ट्रिंग (int)' जोड़ा है। यदि नहीं, तो मुझे लगता है कि आप भाग्य से बाहर हैं। –

+0

मुझे आश्चर्य है कि यह पास जीसीसी है, यह बदसूरत त्रुटियों/चेतावनियों के लिए जाना जाता है, लेकिन मुझे यहां कुछ उम्मीद थी। क्या आपने चेतावनी स्तर को क्रैंक किया था? –

+0

@Maththieu मुझे कोई विकल्प नहीं मिला जो मुझे चेतावनी देता है, लेकिन मैं वास्तव में जीसीसी चेतावनी विकल्पों में नहीं हूं। '-W -Wall -Wpointer-arith -Wcast-qual' किसी भी दर पर चाल नहीं करता है। – leftaroundabout

उत्तर

10

यह बदसूरत की तरह है, लेकिन आप एक टेम्पलेट है कि एक त्रुटि जब instantiated का उत्पादन करेगा बना सकते हैं: तो फिर इसे का उपयोग

template <typename T> 
void bar(T const&) 
{ 
    T::youHaveCalledBarWithSomethingThatIsntAStringYouIdiot(); 
} 

void bar(std::string const& s, int i = 1) 
{ 
    // Normal implementation 
} 

void bar(char const* s, int i = 1) 
{ 
    bar(std::string(s), i); 
} 

:

bar(0); // produces compile time error 
bar("Hello, world!"); // fine 
+5

+1 हालांकि यह दृष्टिकोण विफल रहता है, हालांकि 'टी' वास्तव में 'यूहेव कॉलेडबैरथथिंग थॉट इन्सटैसिंग यूआईडियोट' नामक सार्वजनिक स्थैतिक विधि है और कोई तर्क नहीं लेता है;) –

1

एक कुछ हद तक साफ वैकल्पिक हल ...

#include <cassert> 

void foo (const std::string &s) 
{ 
    // Your function 
} 

void foo(const char *s) 
{ 
    assert(s != 0); 
    foo(std::string(s)); 
} 
+0

यह रन-टाइम है, संकलन-समय नहीं। – robert

+0

@robert मुझे पता है, यह सिर्फ एक संभावित समाधान है। –

-1

असल में स्थिर आवेषण भी काम करेंगे। इस पर विचार करें:

void foo (const std::string &s) 
{ 
    // Your function 
} 

void foo(const char *s) 
{ 
    #ifdef CPP_OH_X 
    static_assert(s == 0, "Cannot pass 0 as an argument to foo!"); 
    #else 
    typedef int[(s != 0) ? 1 : -1] check; 
    #endif 
    foo(std::string(s)); 
} 

विचार यहाँ static_assert जो C++ एक आगामी सुविधा है और पहले से ही विभिन्न compilers में कार्यान्वित किया जाता का उपयोग है; प्राथमिक रूप से वे जो C++ 0x का समर्थन करते हैं। अब यदि आप सी ++ 0x का उपयोग नहीं कर रहे हैं तो आप वैकल्पिक विधि का उपयोग कर सकते हैं, जो मूल रूप से विफलता पर नकारात्मक मान के साथ एक पूर्णांक टाइप करता है। कुछ जो अनुमति नहीं है और संकलन समय

+0

यह निश्चित रूप से टेम्पलेट हैक की तुलना में क्लीनर दिखता है, लेकिन यह काम नहीं कर रहा है: 'implctstringparam.cpp: फ़ंक्शन 'शून्य foo (const char *)': implctstringparam.cpp: 9: त्रुटि: 's' में दिखाई नहीं दे सकता एक निरंतर अभिव्यक्ति ' – leftaroundabout

+0

कॉन्स std :: स्ट्रिंग और एस को काम करने के लिए स्थिर दावे के लिए सबसे अधिक स्थिर आवृत्ति होने की आवश्यकता होगी। – graphitemaster

+1

's' का मान केवल रनटाइम पर जाना जाता है, जब फ़ंक्शन को कॉल किया जाता है: आप इसे 'static_assert' में उपयोग नहीं कर सकते, जिसका संकलन समय पर मूल्यांकन किया जाता है। एक 'static_assert' केवल निरंतर अभिव्यक्तियों का मूल्यांकन कर सकता है। –

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

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