Typ Konvertierungs Operator

02/05/2014 - 23:53 von Markus Raab | Report spam
Hallo Gruppe,

Warum verhàlt sich der Typ Konvertierungs Operator unterschiedlich für int
(bzw. grundlegende Typen) und std::string?

#include <iostream>
#include <string>

class Integer
{
public:
operator int() const
{
return 20;
}
};

class String
{
public:
operator std::string() const
{
return "hello";
}
};

int main()
{
Integer i;
std::cout << i << std::endl;

String s;
std::cout << s << std::endl;
}

i kann problemlos ausgegeben werden, s aber nicht. Explizites konvertieren
nach std::string funktioniert problemlos. const char* statt std::string
funktioniert auch problemlos.

g++ -std=c++0x -Wall -Wextra `pkg-config --cflags elektra` -ggdb -O0 `pkg-
config --libs elektra` -pthread first.cpp -o first
first.cpp: In function ‘int main()’:
first.cpp:27:16: error: cannot bind ‘std::ostream {aka
std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
In file included from /usr/include/c++/4.7/iostream:40:0,
from first.cpp:1:
/usr/include/c++/4.7/ostream:600:5: error: initializing argument 1 of
‘std::basic_ostream<_CharT, _Traits>&
std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with
_CharT = char; _Traits = std::char_traits<char>; _Tp = String]’
make: *** [first] Fehler 1

mfg Markus
 

Lesen sie die antworten

#1 Daniel Krügler
03/05/2014 - 15:15 | Warnen spam
Am Freitag, 2. Mai 2014 23:53:47 UTC+2 schrieb Markus Raab:
Hallo Gruppe,

Warum verhàlt sich der Typ Konvertierungs Operator unterschiedlich für int
(bzw. grundlegende Typen) und std::string?



Deine Vermutung geht in die falsche Richtung, die Ursache liegt *nicht* in unterschiedlichem Verhalten der Konvertierungsfunktionen, Details weiter unten (Hinweis: Technisch ist der Begriff "Konvertierungsoperator" hier nicht gültig, er würde dann sowas wie einen static_cast, dynamic_cast, etc. bezeichnen).

#include <iostream>
#include <string>

class Integer
{
public:
operator int() const
{
return 20;
}
};

class String
{
public:
operator std::string() const
{
return "hello";
}
};

int main()
{
Integer i;
std::cout << i << std::endl;



Dieser Ausdruck ist gültig, weil der Compiler herausfindet, dass std::ostream eine Element-Funktion

std::ostream& std::ostream::operator<<(int n);

hat und weil Integer eine eindeutige Konvertierung zu int anbietet.

String s;
std::cout << s << std::endl;



Hier ist die Sache unterschiedlich: std::ostream hat keine Member-Funktion, die einen std::string aufnimmt, stattdessen gibt es aber im Header <string> ein freies Funktionstemplate:

template<class charT, class traits, class Allocator>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os,
const basic_string<charT,traits,Allocator>& str);

Dieses Funktionstemplate hat einen abhàngigen Parameter

const basic_string<charT,traits,Allocator>&

aber dieser wird nur erfolgreich deduziert, wenn das reale Argument eine Instanz von basic_string<charT,traits,Allocator> ist. In deinem Fall ist dies aber nicht zutreffend, das reale Argument hat den Typ ::String und wird daher nicht deduziert (Konvertierungen werden bei Templatededuktionen nicht berücksichtigt - Dies ist "by Design").

Besten Gruss aus Bremen,

Daniel Krügler

Ähnliche fragen