2017-05-20 11 views
11

मेरा std::variant खाली हो सकता है (std::monostate), int, std::string या bool शामिल है।मेरा संस्करण एक std :: स्ट्रिंग को एक बूल में क्यों परिवर्तित करता है?

जब मैं इसे var = "this is my string" के रूप में दिया गया स्ट्रिंग के साथ फ़ीड करना चाहता हूं, तो यह bool में परिवर्तित हो जाता है और स्ट्रिंग पर नहीं। अगर मैं स्पष्ट रूप से इस प्रकार की घोषणा करता हूं, तो यह var = std::string("this is my string") काम करता है। ऐसा क्यों है और ऐसा कुछ है जो मैं इससे बचने के लिए कर सकता हूं?

#include <string> 
#include <variant> 
#include <iostream> 

int main() 
{ 
    using var = std::variant<std::monostate, int, std::string, bool>; 

    var contains_nothing;  
    var contains_int = 5; 
    var contains_string = "hello"; 
    var contains_expl_string = std::string("explicit hello"); 
    var contains_bool = false; 

    auto visitor = [](auto&& arg){ 
      using T = std::decay_t<decltype(arg)>; 
      if constexpr (std::is_same<T, std::monostate>()) 
       std::cout<<"nothing\n"; 
      else if constexpr (std::is_same<T, int>()) 
       std::cout<<"int: "<<arg<<"\n"; 
      else if constexpr (std::is_same<T, std::string>()) 
       std::cout<<"string: "<<arg<<"\n"; 
      else if constexpr (std::is_same<T, bool>()) 
       std::cout<<"bool: "<<arg<<"\n"; 
      else 
       std::cout<<"Visitor is not exhaustive\n"; 
     }; 

    std::visit(visitor, contains_nothing);  // nothing 
    std::visit(visitor, contains_int);   // int: 5 
    std::visit(visitor, contains_string);  // bool: 1 
    std::visit(visitor, contains_expl_string); // string: explicit hello 
    std::visit(visitor, contains_bool);   // bool: 0  
} 

संपादित चूंकि मेरे कोड के उपयोगकर्ताओं को स्पष्ट रूप से string रों नहीं हो सकता है, मुझे लगता है कि पकड़ने के लिए पसंद करते हैं। अन्यथा यह त्रुटि का स्रोत होगा। मैंने टेम्पलेट-हेल्पर फ़ंक्शन बनाया है जो जांचता है कि char* पारित किया गया है और यदि ऐसा है, तो std :: स्ट्रिंग बनाता है। अच्छा काम करता है। इस सरल की सराहना करने में मदद की सराहना की है!

संपादित 2 के रूप में डिफ़ॉल्ट पैरामीटर/प्रकार std::monostate घोषित करने से, यह भी जब make_var किसी भी तर्क के बिना कहा जाता है काम करता है।

#include <string> 
#include <variant> 
#include <iostream> 

using var = std::variant<std::monostate, int, std::string, bool>; 

template<typename T = std::monostate> 
var make_var(T value = std::monostate()) 
{ 
    if constexpr (std::is_same<typename std::remove_const<typename std::decay<T>::type>::type, const char*>()) 
     return std::string(value); 
    return value; 
} 

int main() 
{ 
    auto contains_nothing = make_var();  
    auto contains_int = make_var(3); 
    auto contains_string = make_var("hello"); 
    auto contains_expl_string = make_var(std::string("excplicit hello")); 
    var contains_bool = make_var(false); 

    auto visitor = [](auto&& arg){ 
      using T = std::decay_t<decltype(arg)>; 
      if constexpr (std::is_same<T, std::monostate>()) 
       std::cout<<"nothing\n"; 
      else if constexpr (std::is_same<T, int>()) 
       std::cout<<"int: "<<arg<<"\n"; 
      else if constexpr (std::is_same<T, std::string>()) 
       std::cout<<"string: "<<arg<<"\n"; 
      else if constexpr (std::is_same<T, bool>()) 
       std::cout<<"bool: "<<arg<<"\n"; 
      else 
       std::cout<<"Visitor is not exhaustive\n"; 
     }; 

    std::visit(visitor, contains_nothing); 
    std::visit(visitor, contains_int); 
    std::visit(visitor, contains_string); 
    std::visit(visitor, contains_expl_string); 
    std::visit(visitor, contains_bool);  
} 
+2

एक और सवाल पूछने के लिए, क्यों 'std :: को प्राथमिकता दी जानी चाहिए स्ट्रिंग' है 'bool'? दोनों को सरणी क्षय और प्रकार रूपांतरण की आवश्यकता होती है। – juanchopanza

+1

http://stackoverflow.com/questions/44021989/implicit-cast-from-const-string-to-bool विशेष रूप से मेरे टेम्पलेट का उपयोग करके मेरे कामकाज के लिए मेरा प्यारा उत्तर देखें ;-)। लेकिन एंग्यू का उपयोग एक उपयोगकर्ता परिभाषित शाब्दिक (नीचे) का उपयोग होता है। – Bathsheba

+0

संक्षिप्त उत्तर: ऐसा नहीं है, क्योंकि यह एक 'std :: string' नहीं है जिसे आपने दिया था। –

उत्तर

27

"hello" के प्रकार const char [6] जो const char * को decays है। const char * से bool का रूपांतरण एक अंतर्निहित रूपांतरण है, जबकि const char * से std::string का रूपांतरण उपयोगकर्ता द्वारा परिभाषित रूपांतरण है, जिसका अर्थ है कि पूर्व किया गया है।

आप सी ++> = 14 का उपयोग कर रहे हैं, इसलिए आपको निरूपित करने के लिए शाब्दिक प्रत्यय s उपयोग कर सकते हैं एक std::string शाब्दिक:

using namespace std::string_literals; 

var contains_string = "hello"s; 
+1

यह 'बूल' के बजाय 'int' प्रकार क्यों नहीं उठाया? – skypjack

+15

@skypjack क्योंकि C++ में 'int' रूपांतरण के लिए कोई अंतर्निहित सूचक नहीं है। – Angew

+0

यह वास्तव में समझ में आता है। धन्यवाद।:-) – skypjack

4

"hello", एक std::string नहीं है, यह एक const char * है और यह परोक्ष और साथ ही एक std::string निर्माण करने के लिए इस्तेमाल किया bool करने के लिए परिवर्तित किया जा सकता है।
अन्य शब्दों में, यह ठीक काम करता है:

int main() { 
    bool b = "foo"; 
    (void)b; 
} 

@aschepler द्वारा टिप्पणी में उल्लेख किया है:

bool करने के लिए const char* से अंतर्निहित रूपांतरण const char* से उपयोगकर्ता-निर्धारित रूपांतरण से अधिक पसंद किया जाता है std::string पर। int बिल्कुल एक विकल्प नहीं है।

+0

यहां कोई यूबी नहीं है। 'कॉन्स्ट char *' से 'bool' के अंतर्निहित रूपांतरण को उपयोगकर्ता द्वारा परिभाषित रूपांतरण पर' const char * 'से' std :: string' तक प्राथमिकता दी जाती है। 'int' बिल्कुल एक विकल्प नहीं है। – aschepler

+0

@aschepler धन्यवाद, निश्चित। – skypjack

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

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