Hallo,
ich habe bisher wenig bis keine Erfahrung mit C++ und darf jetzt Code
eines Kollegen erweitern, der nicht mehr greifbar ist. Es gibt eine
Klasse 'Message' mit den beiden Konstruktoren:
message.cpp
Wenn ich den oben auskommentierten dritten Konstruktor hinzufüge, kann
sich der Kompiler an anderer Stelle nicht mehr für einen Konstruktor
entscheiden, da dann zwei in Frage kommen.
Micha schrieb:> Ich möchte jetzt ein Objekt dieser Klasse mit einem std::string> instanzieren.
Da die Konstruktoren von Message nur entweder eine Initializer-List mit
uint8_t-Werten oder einen Vector mit uint8_t-Werten haben wollen, geht
das nicht.
Jetzt könnte man vermuten, daß diese uint8_t-Werte ASCII-Zeichen sein
könnten. Das musst du aber selber aus den Sourcen heraus knobeln.
Wenn das so ist, nimm die Zeichen des Strings, schreib die in einen
Vector<uint8_t>, dann klappt es auch mit dem Konstruktor.
Der auskommentierte dritte Konstruktor allerdings sollte einfach so
funktionieren.
Micha schrieb:> return Message{ { buffer.begin(), buffer.end() } };
Wer hat denn diese Zeile geschrieben?
Oliver
Oliver S. schrieb:> Der auskommentierte dritte Konstruktor allerdings sollte einfach so> funktionieren.
Tut er auch - an dieser Stelle. Dafür entsteht ein Fehler an besagter
anderer Stelle.
Oliver S. schrieb:> Micha schrieb:>> return Message{ { buffer.begin(), buffer.end() } };>> Wer hat denn diese Zeile geschrieben?
Der damalige Autor an einer ganz anderen Stelle im Code.
Micha schrieb:> Der damalige Autor an einer ganz anderen Stelle im Code.
Tja, dann hat entweder das noch nie compiliert, oder du hast nicht allen
Code von Message gezeigt. Im letzteren Fall wirst das Problem selber
lösen müssen.
Oliver
Oliver S. schrieb:> Tja, dann hat entweder das noch nie compiliert, oder du hast nicht allen> Code von Message gezeigt. Im letzteren Fall wirst das Problem selber> lösen müssen.
Es kompiliert solange ich "meinen" Konstruktor auskommentiert lasse.
Sobald ich den aber dazu kompilieren möchte, kann sich der Kompiler
nicht mehr zwischen dem ersten (?) und dem dritten Konstruktor
entscheiden.
In Message ist noch mehr drin, aber das imo relevante hab ich gepostet.
Dank deines Hinweises habe ich es jetzt auch kompiliert, nachdem ich
1
// send messages
2
for(constauto&dataSet:identifier)
3
{
4
sendMessage(Message{dataSet});// dataSet.c_str() also doesn't work
Oliver S. schrieb:> Das würde ich an der Stelle als guten Programmierstil ansehen.
Super! Nochmals vielen Dank! Damit läuft auch die Variante mit dem 3.
Konstruktor.
Fehlermeldung passt nicht zum gezeigten Code. Wenn Du auch in der Lage
sein möchtest, eine Message von einem `const char*` zu konstruieren
(z.B. string literals), dann solltest Du einen entsprechenden Konstrukt
hinzufügen. Ansonsten gibt es keinen Grund, warum der gezeigte Code
nicht funktionieren sollte.
>
1
>{
2
>std::vector<std::uint8_t>buffer(nubmerOfBytes);
3
>// some code
4
>returnMessage{{buffer.begin(),buffer.end()}};
5
>}
6
>
`buffer` ist vom Typen `std::vector<std::uint8_t>` und die korrekte
Syntax, um damit einen Message zu konstruieren, wäre:
1
returnMessage(buffer);
`{ buffer.begin(), buffer.end() }` wäre vom Typen
`std::initializer_list<std::vector<std::uint8_t>::iterator>` und dafür
gibt es keinen Konstruktor.
> Wie kann ich das Problem lösen?
Immer aufmerksam die Fehlermeldung lesen ;-)
Torsten R. schrieb:> `{ buffer.begin(), buffer.end() }` wäre vom Typen> `std::initializer_list<std::vector<std::uint8_t>::iterator>` und dafür> gibt es keinen Konstruktor.
Da wird erst der Konstruktor für vector(itarator, iterator) aufgerufen,
und damit dann der von Message(vector). Da vector ein Template ist,
funktioniert das so. Erst, wenn da String ins Spiel kommt, für den es
ebenfalls einen Konstruktor String(iterator, iterator) gibt, wird das
uneindeutig.
Die Fehlermeldungen sind schon alle richtig.
Oliver
Oliver S. schrieb:> Da wird erst der Konstruktor für vector(itarator, iterator) aufgerufen,> und damit dann der von Message(vector). Da vector ein Template ist,> funktioniert das so.
Das hat wenig damit zu tun, dass `std::vector<>` ein Template ist
(`std::basic_string<>` ist auch ein Template), sondern damit, dass eine
Konvertierung nötig ist (weil es eben keinen c'tor für
`std::initializer_list<std::vector<std::uint8_t>::iterator>` gibt) und
die Konvertierung dann nicht eindeutig ist, weil `std::uint8_t` (bzw.
boost::asio::detail::buffered_stream_storage::byte_type) wahrscheinlich
ein Alias für `char` ist.
Torsten R. schrieb:> weil std::uint8_t` (bzw.> boost::asio::detail::buffered_stream_storage::byte_type) wahrscheinlich> ein Alias für `char` ist.
Das 'u' in uint8_t lässt vermuten, daß das mit ziemlicher Sicherheit ein
unsigned char ist ;) (Und boost ist da auch nicht dabei)
Und ein std::string ist kein std::vector<char>. Da gibt es keinerlei
möglichen Mehrdeutigkeiten.
Das Problem, welches mit dem Konstruktor Message(string) zur
Fehlermeldung führt, kommt daher, daß es dann zwei gleichwertige
Möglichkeiten zur Auflösung des impliziten cast von {iterator, iterator}
zu einem von Message akzeptierten Typ gibt.
Oliver