2016-07-17 9 views
-1

Haftungsausschluss: Das ist wird lahm.C++: Art von "solchen Strings". Einen Funktionsaufruf machen wie Spaß ("str") Arbeit

Zwei Fragen:

  1. Der von der Neugier getrieben Teil: Was ist die genaue Art eines Zitat markierten Zeichenfolge? Prevoiusly dachte ich, dass es eine C char[] String std::string umgewandelt, wenn es gebraucht wird, aber einige type_traits Experimente zeigten dies:

    std::is_lvalue_reference<decltype ("string")>::value; -> true 
    std::is_object<std::remove_reference<decltype ("string")>>::value; -> true 
    std::is_same<decltype ("string"), std::string&>::value; -> false 
    
  2. Der lahme Teil: welche Art von Argument sollte mit einer Funktion übernehmen zu können, beschäftigen Anrufe wie fun("str")? Der Grund für diese Frage ist, dass das folgende Beispiel nicht kompiliert wegen der static_assert:

    template <typename T> 
    void fun (const T &what) 
    { 
        static_assert(sizeof(T) < 0, "Something unsupported"); 
    } 
    
    void fun (std::string str) 
    { 
        std::cout << "Copied" << std::endl; 
    } 
    
    void fun (const std::string &str) 
    { 
        std::cout << "Lvalue" << std::endl; 
    } 
    
    void fun (std::string &&str) 
    { 
        std::cout << "Rvalue" << std::endl; 
    } 
    
    int main() 
    { 
        fun ("str"); //static assertion failed 
        return 0; 
    } 
    

    Mehr über, kommentiert die Vorlage verursacht aus

    error: call of overloaded 'fun(const char [4])' is ambiguous 
    candidates are: [all three options] 
    

    Es ist nicht zweideutig scheint mir. Warum erstellt es keine temporäre Zeichenkette und übergibt sie an rvalue-reference?

+0

Es ist ein Zeiger auf eine Konstante (schreibgeschützt) Null-terminiert (endet mit '\ 0') Array von' Char's. –

+0

@barakmanos Warum zeigten die 'type_traits', dass es sich nicht um einen Zeiger handelt, sondern um einen lvalue-Bezug auf ein Objekt? – Alex

+2

In C++ ist der Typ des String-Literals '" Hello "' 'const char [6]' (ein Array von 6 Elementen vom Typ 'const char'). Das zeigerähnliche Verhalten ist auf die standardmäßige Konvertierung von Array zu Zeiger zurückzuführen. –

Antwort

1

Prevoiusly Ich dachte, dass es ein C char[] String std::string umgewandelt, wenn es gebraucht wird

Schließen. Es ist ein const char [] konvertiert zu std::string, wenn es benötigt wird.

Der lahme Teil: welche Art von Argument sollte wie fun("str") mit Anrufen bewältigen eine Funktion übernehmen zu können?

Sie können std::string verwenden. Sie können const char (&) [N] verwenden. Sie können const char * verwenden. Allerdings ...

Der Grund für diese Frage ist, dass das folgende Beispiel nicht wegen der static_assert nicht kompiliert:

... Sie haben eine Chance zu geben, die Überladungsauflösung. Wenn Sie

template <typename T> 
void fun (const T &what) 
{ 
    static_assert(sizeof(T) < 0, "Something unsupported"); 
} 

haben dann auch wenn Stringliterale zu std::string implizit konvertierbar sind, sagen Sie, dass diese Funktion direkt Stringliterale annehmen kann. Wenn man zwischen einer Funktion, die nach einer impliziten Umwandlung ein String-Literal nimmt, und einer Funktion, die direkt ein String-Literal nimmt, die Funktion wählt, die sie direkt annimmt, wird sie aufgerufen.

Mehr über, kommentieren die Vorlage verursacht aus

error: call of overloaded 'fun(const char [4])' is ambiguous 
candidates are: [all three options] 

nach Wert zwischen Einnahme auswählen und durch Bezugnahme eingeschlossen. Es wäre in Ordnung, eine einzige nicht überladene Funktion zu haben, die std::string wertmäßig nimmt. Es wäre auch in Ordnung, zwei überladene Funktionen zu haben, die std::string durch const & und && Bezug nehmen. Aber nach Wert und als Referenz ist zu viel, gibt es keinen Grund, einen über den anderen dann zu bevorzugen.

+0

Ordentlich! Vielen Dank, dass Sie auf Conversions vs Priority und Passing by Value gegenüber dem Referenzieren hingewiesen haben – Alex

3

Stringliteral "str" hat const char[4] eingeben. Die am besten geeignete Funktion für dieses Argument ist die Template-Funktion, da sie keine Konvertierung in std :: string erfordert.

Verwandte Themen