2016-03-12 17 views
5

यह दूसरी बार है जब मैं एक बड़ी गलती करता हूं, एक डबल की बजाय प्रकार के बूल का एक चर बनाकर। उदाहरण के लिए विचार करनासी ++ डबल से बूल तक अंतर्निहित रूपांतरण खतरनाक है

double f() 
{ 
    return true; 
} 
bool something() 
{ 
    return 0.0; 
} 
double g() 
{ 
    bool x = 0.0; // (1) 
    if (something()) { 
     x = f(); // where f() is a function returning a double 
    } 
    return x; 
} 

मुझे लगता है कि संकलक मुझे बताओ चाहिए कि यह बुरा है, लेकिन मेरी संकलक (छ ++) के साथ -Wall ... एक छोटे से चेतावनी जारी नहीं करता है और यह टेस्ट मैचों में बाद में एक बग की ओर जाता है। क्या gcc/g ++ के लिए चेतावनियां रखने के लिए कुछ विकल्प है (उदाहरण के लिए लाइन 1 पर, यह स्पष्ट रूप से खराब है)?

+0

क्या आपने '-pedantic-त्रुटियों 'की कोशिश की है? –

+0

मैंने अभी कोशिश की: g ++ -Wall -Wextra -pedantic-error -c dummy.cpp और मुझे अभी भी चेतावनियां नहीं हैं। – Renaud

+0

एमएसवीसी 14 इस के लिए [सी 4800] (https://msdn.microsoft.com/en-us/library/b6801kcy.aspx) उत्पन्न करता है। – wally

उत्तर

3

आपको एक त्रुटि प्राप्त करने के लिए वर्दी प्रारंभ उपयोग कर सकते हैं:

bool x{0.0}; 

error: type 'double' cannot be narrowed to 'bool' in initializer list [-Wc++11-narrowing]

यह भी काम पर इस्तेमाल किया जा सकता: x = {f()};, और return {x}; लौटने।

+0

मुझे बूल एक्स {0.0} के साथ कोई चेतावनी नहीं है; मैं mccw-w64 का उपयोग कर रहा हूं gcc-5.2 – Renaud

+1

@ रीनाड कुछ कारणों से जीसीसी इस व्यवहार को लागू नहीं करता है। अगर आप इस सुविधा का उपयोग करना चाहते हैं तो मैं क्लैंग का उपयोग करने की सलाह दूंगा। – emlai

+0

@ रेनाड: यह जीसीसी में बग लगता है। [Http://melpon.org/wandbox/permlink/ 5vqO6rRq8x8sNiix] (http://example.com) – Destructor

0

सी ++ में, कोडर को स्वयं को संभालने के लिए मजबूर करना, रनटाइम के लिए संसाधनों को मुक्त करता है। कीमत प्रकारों का ट्रैक रख रही है, लेकिन लाभ प्रभावशीलता और गति है।

इसका भुगतान करने के लिए एक छोटी सी कीमत है, लेकिन इनाम कम समय में और अधिक करने की क्षमता है।

+0

"कोडर को खुद को संभालने के लिए मजबूर करना, रनटाइम के लिए संसाधनों को मुक्त करता है"। सी ++ स्थिर रूप से टाइप किया गया है यानी सभी प्रकार संकलित समय पर चेक किए जाते हैं, इसलिए रनटाइम के प्रकारों के बारे में कुछ भी नहीं है। – emlai

1

विज़ुअल सी ++ कंपाइलर bool पर रूपांतरण के बारे में चेतावनी देता है, लेकिन एक मूर्ख प्रदर्शन चेतावनी के साथ। आम तौर पर यह एक अवांछित चेतावनी है, लेकिन दुर्भाग्य से इसे एक साधारण कलाकार के साथ चुप नहीं किया जा सकता है। इसे शांत करने के लिए लगभग मुहावरे एक डबल अस्वीकृति का उपयोग करना है, !!, बैंग-बैंग, उदा। return !!0.0

आपकी समस्या विपरीत है, कि आप ऐसी चेतावनी या त्रुटि चाहते हैं, लेकिन फिर भी बैंग-बैंग लगभग-मुहावरे समाधान का हिस्सा हो सकता है।

विचार नीचे एक उदाहरण प्रस्तुत किया साथ

, तो आप बस bool जहां एक बूलियन चाहते के बजाय Bool लिखते हैं, और !! का उपयोग स्वच्छ bool मान यह सुनिश्चित करने, वरना आप संकलन त्रुटियों मिलता है।

इस बारे में अच्छी बात यह है कि संभवतः आप केवलके साथ bool को बदलकर, अपने कोड में वैश्विक खोज कर सकते हैं और प्रतिस्थापित कर सकते हैं।

#ifdef CLEAN 
# define TO_BOOL !! 
#else 
# define TO_BOOL 
#endif 

#define STATIC_ASSERT(e) static_assert(e, #e) 

#include <type_traits> // std::is_same 
#include <utility>  // std::enable_if_t 

class Bool 
{ 
private: 
    bool value_; 

public: 
    operator bool() const { return value_; } 

    template< class T 
     , class Enabled_ = std::enable_if_t<std::is_same<T,bool>::value, void> 
     > 
    auto operator=(T const other) 
     -> Bool& 
    { value_ = other; return *this; } 

    Bool(): value_() {} 

    template< class T 
     , class Enabled_ = std::enable_if_t<std::is_same<T,bool>::value, void> 
     > 
    Bool(T const value) 
     : value_(value) 
    {} 
}; 

auto f() 
    -> double 
{ return 0.0; } 

auto something() 
    -> Bool 
{ return TO_BOOL 0.0; }       // ← Line 43 

auto g() 
    -> double 
{ 
    Bool x = TO_BOOL 0.0;      // ← Line 48 
    if (something()) { 
     x = TO_BOOL f(); // where f() is a function returning a double 
    } 
    return x; 
} 

auto main() -> int 
{ 
    Bool a, b, c; 
    return a && b || something(); 
} 

जी के साथ ++ उदाहरण संकलन:

 
c:\my\forums\so\105> g++ foo.cpp 
foo.cpp: In function 'Bool something()': 
foo.cpp:43:22: error: could not convert '0.0' from 'double' to 'Bool' 
    { return TO_BOOL 0.0; }       // ← Line 43 
        ^
foo.cpp: In function 'double g()': 
foo.cpp:48:25: error: conversion from 'double' to non-scalar type 'Bool' requested 
     Bool x = TO_BOOL 0.0;      // ← Line 48 
         ^
foo.cpp:50:13: error: no match for 'operator=' (operand types are 'Bool' and 'double') 
      x = TO_BOOL f(); // where f() is a function returning a double 
      ^
foo.cpp:23:14: note: candidate: template<class T, class Enabled_> Bool& Bool::operator=(T) 
     auto operator=(T const other) 
      ^
foo.cpp:23:14: note: template argument deduction/substitution failed: 
foo.cpp:12:11: note: candidate: Bool& Bool::operator=(const Bool&) 
    class Bool 
     ^
foo.cpp:12:11: note: no known conversion for argument 1 from 'double' to 'const Bool&' 
foo.cpp:12:11: note: candidate: Bool& Bool::operator=(Bool&&) 
foo.cpp:12:11: note: no known conversion for argument 1 from 'double' to 'Bool&&' 
foo.cpp: In function 'int main()': 
foo.cpp:58:18: warning: suggest parentheses around '&&' within '||' [-Wparentheses] 
     return a && b || something(); 
       ^

c:\my\forums\so\105> g++ foo.cpp -D CLEAN 
foo.cpp: In function 'int main()': 
foo.cpp:58:18: warning: suggest parentheses around '&&' within '||' [-Wparentheses] 
     return a && b || something(); 
       ^

c:\my\forums\so\105> g++ foo.cpp -D CLEAN -Wno-parentheses 

c:\my\forums\so\105> _ 

आप कुछ अन्य प्रकार की तुलना में bool विचार नहीं किया जा करने के लिए करने के लिए Bool से अंतर्निहित रूपांतरण चाहते हैं, बस भी है कि रूपांतरण ऑपरेटर एक जाँच टेम्पलेट बनाने के लिए, निर्माता की तरह और असाइनमेंट ऑपरेटर।

+0

"प्रदर्शन" पहलू एक तरफ, पठनीयता पर आपकी राय क्या है? भले ही यह स्पष्ट रूप से वीसी चेतावनी का इरादा नहीं है, फिर भी मैंने इसे अक्सर कोड को इंगित किया है जिसे स्पष्ट जांच के साथ बहुत स्पष्ट किया जा सकता है। उदाहरण के लिए, 'डबल एक्स = 0.0; बूल बी = (एक्स! = 0.0); 'बनाम' डबल एक्स = 0.0; बूल बी = एक्स; '। –

2

हालांकि मैं एक सीधा जवाब नहीं है (एक संकलक चेतावनी के लिए कहा गया था), मैं एक opaque typedef library एक "inconvertibool" प्रकार जो की तरह और bool के साथ काम करता युक्त, लेकिन पूर्णांक या डबल जैसे अन्य प्रकार के साथ नहीं है।यह संकलन समय के मामलों के लिए त्रुटियों अपने उदाहरण में देता है:

foo.cpp: In function 'double f()': 
foo.cpp:5:31: error: cannot convert 'inconvertibool {aka opaque::inconvertibool}' to 'double' in return 
    return inconvertibool(true); 
          ^
foo.cpp: In function 'inconvertibool something()': 
foo.cpp:9:12: error: could not convert '0.0' from 'double' to 'inconvertibool {aka opaque::inconvertibool}' 
    return 0.0; 
      ^
foo.cpp: In function 'double g()': 
foo.cpp:13:23: error: conversion from 'double' to non-scalar type 'inconvertibool {aka opaque::inconvertibool}' requested 
    inconvertibool x = 0.0; // (1) 
        ^
foo.cpp:15:9: error: no match for 'operator=' (operand types are 'inconvertibool {aka opaque::inconvertibool}' and 'double') 
     x = f(); // where f() is a function returning a double 
     ^
बेशक

, यह केवल मदद मिलेगी अगर आप लगातार bool के बजाय इस प्रकार का उपयोग करें, लेकिन यह काफी अपने परिदृश्य से मेल नहीं खाता है क्योंकि आप आपने कहा मतलब 'डबल', 'बूल' नहीं।

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