Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);"
-
@Jockelx sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":
@martin_zi Und wo sagt dir dein Kompiler, dass er hier den std::initializer mag? Er mag einen Konstructor der mit const char[2] irgendwie umgehen kann, z.B. ein Konstruktor, der einen std::string erwartet.
Weil mir die Fehlermeldung irgendwie derzeit zu unverständlich ist interpretiere ich einfach irgendwas hinein. Aber du hast recht ich habe da was gemixt. Wenn ich dieses std::initializer_list<int> list habe kanne ich das machen:
MyClass elements3 = {"0", "1", "2", "3" }; //und nicht das: MyClass elements2[] = {"0", "1", "2", "3" };
Der Hinweis mit der [] war mir aber zu wenig und habe ich erst jetzt verstanden was du meinst.
Allerdings muss ich meine Klasse so bauen:
class MyClass { public: MyClass() { } MyClass(const char *mychar) { } }
Sollte das auch funktionieren ?
class MyClass { public: MyClass() { } MyClass(std::string mychar) { } }
Mit std::string gibt es immer noch dieselbe Fehlermeldung.
-
@martin_zi sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":
Ja und mein compiler mag das nicht: "error: conversion from 'const char [2]' to non-scalar type 'MyClass' requested"
Du kannst die Elemente einzeln initialisieren:
MyClass elements[] = {{"0"}, {"1"}, {"2"}, {"3"}};
-
Vielleicht etwas Code zum Verständnis wieso, weshalb, warum:
#include <vector> #include <iostream> struct A { A(int i) {} A(int i, int j) {} }; int main() { std::vector<A> a = {{1,2}, 3}; std::cout << a.size(); }
-
@martin_zi
C++ hat die Regel dass immer nur eine "user defined conversion" implizit angewendet wird. D.h. wenn du etwas hast was einFoo
braucht, undFoo
ist mit einemstd::string
erzeugbar, und derstd::string
ist mit einemconst char*
erzeugbar, dann kannst du da nicht einfach "blah" hinschreiben.
Weil dazu zwei "user defined conversions" nötig wären:
1x "eingebaute conversion"const char[5]
->const char*
1x "user defined"const char*
->std::string
1x "user defined"std::string
->Foo
Also Beispiel
void takeFoo(Foo f); void test() { takeFoo("blah"); // geht nicht weil zwei "user defined conversions" nötig takeFoo(std::string{"blah"}); // geht weil nur eine "user defined conversion" nötig takeFoo({"blah"}); // geht auch weil nur eine "user defined conversion" nötig // {"blah"} wird hier als Initialisierung des std::string interpretiert // und danach kommt 1x implizite konvertierung von std::string nach Foo }
Zum Initialisieren eines Arrays brauchst du erstmal die
{}
. Bei einemMyClass
Array müssen die Werte innerhalb der{}
also geeignet seinMyClass
Objekte zu initialisieren. D.h.{"a", "b"}
ist vergleichbar mittakeFoo("blah")
im Beispiel oben, geht also nicht.Bei
{{"a"}, {"b"}}
dagegen werden{"a"}
und{"b"}
als Initialisierung einesstd::string
verstanden, und dann kann mit nur einer "user defined conversion" einMyClass
Objekt gebastelt werden.
-
@martin_zi sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":
Ja und mein compiler mag das nicht: "error: conversion from 'const char [2]' to non-scalar type 'MyClass' requested"
Es hat schon seinen Grund, dass in meinem vollständigen Beispiel die Klasse keinen Konstruktor hat.
-
@manni66 Das ist aber wieder ein Spezialfall (alles public Member, keine special member functions etc.). Und mMn. nix was man besonders pushen sollte.
-
@manni66 sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":
@martin_zi sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":
Ja und mein compiler mag das nicht: "error: conversion from 'const char [2]' to non-scalar type 'MyClass' requested"
Es hat schon seinen Grund, dass in meinem vollständigen Beispiel die Klasse keinen Konstruktor hat.
Äääämmm ahhhhh ja aber genau bei solchen Sachen habe ich ein Verständnis Problem.
Ich erzähle mal so wie ich es verstehe und dann kann man mich korrigieren:Laut Buch und was ich sonst so finde gilt: "Falls kein Konstruktor angegeben wird, wird einer vom System automatisch erzeugt (implizite Konstruktordeklaration)."
Damit hat eine Klasse auch wenn nicht angegebn einen Konstruktor.Will ich wirklich keinen haben muss ich mit delete arbeiten. Also:
class MyClass { MyClass() = delete; };
Weiter steht:
Dieser vordefinierte Konstruktor (englisch default constructor) kann auch selbst
geschrieben werden. Der Standard-konstruktor hat keine Parameter. Für eine Klasse X wird er einfach mit X(); deklariert.Für mich bedeutet das:
class MyClass { public: MyClass() { } sinnlos = myString; };
class MyClass { public: sinnlos = myString; };
Das dass das Gleiche ist. Aber das ist wohl nicht so. Also woher weiß ich was der Compiler wirklich generiert ? Da ist ja dann wohl was da, was ich gar nie geschrieben wurde. Und schreibe ich zuviel ist auf einmal doch was weg
-
@martin_zi sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":
Das dass das Gleiche ist. Aber das ist wohl nicht so.
Nein, ist es nicht.
-
@hustbaer sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":
@manni66 Das ist aber wieder ein Spezialfall (alles public Member, keine special member functions etc.).
Ja, entsprechend dem sinnlosen Beispiel.
Und mMn. nix was man besonders pushen sollte.
Nein, es ging auch nur um das "bei mir geht ea aber nicht".
-
@martin_zi
Der Konstruktor ist schon fast der selbe, darum geht's aber nicht. Selbst wenn der 100% identisch wäre ginge es nicht.Es geht darum: https://en.cppreference.com/w/cpp/language/aggregate_initialization
-
@manni66 sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":
@hustbaer sagte in Was mache ich hier ? "std::vectorstd::string myAllArgs(argv, argv + argc);":
||| @manni66 Das ist aber wieder ein Spezialfall (alles public Member, keine special member functions etc.).
Ja, entsprechend dem sinnlosen Beispiel.
||| Und mMn. nix was man besonders pushen sollte.
Nein, es ging auch nur um das "bei mir geht ea aber nicht".
Der Hinweis hat schon gepasst, vielleicht war es nicht ganz das Thema aber es hat mit was gezeigt was ich nicht ganz bzw. sogar falsch verstanden habe.
@hustbaer
Und danke auch für den Hinweis mit diesem link.Aber zurück zum Anfangs Thema:
Einen Vector erzeuge ich so:
vector<int> vec1;
Oder so:
vector<int> vect(0, 10);
wenn ich nicht den default Konstruktor aufrufen will.
Bzw am Ende so wie in der Anfangsfrage auch so:vector<string> myAllArgs(argv, argv + argc);
Also bräuchte meine Klasse die das können soll in etwa sowas:
template<typename _Tp> class MyVector { public: MyVector() { cout << "ctor MyVector" << endl; } MyVector(_Tp element,int size) { // TODO! } MyVector(_Tp &firstElement, _Tp &lastElement) { _Tp *pf,*pl; pf = &firstElement; pl = &lastElement; while (pf <= pl) { mylist.push_back(*pf); pf++; } } td::list<_Tp> mylist; };
Ok und dann halt noch den Rest der Methoden die ich jetzt aus Faulheit unterschlagen habe...
Also wie Sepp und manni66 schon geschrieben haben einen anderen Vector-Konstruktor aufgerufen. Ist jetzt nicht so elegant aber für mich jetzt etwas verständlicher. Gibts sonst noch wo Logik- oder Denkfehler bei mir ?
-
@martin_zi sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":
MyVector(_Tp &firstElement, _Tp &lastElement)
Das ist aber ein merkwürdiger Konstruktor!
Vergleiche mit (4) auf https://en.cppreference.com/w/cpp/container/vector/vector
-
@wob sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":
@martin_zi sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":
MyVector(_Tp &firstElement, _Tp &lastElement)
Das ist aber ein merkwürdiger Konstruktor!
Vergleiche mit (4) auf https://en.cppreference.com/w/cpp/container/vector/vector
Ja aber besser konnte ich es derzeit nicht lösen bin noch am Anfang....
template< class InputIt > vector( InputIt first, InputIt last, const Allocator& alloc = Allocator() );
Und hier verstehe ich nicht was Allocator sein soll.
std::vector<T,Allocator>::vector
Es ist zwar hier aber ich erzeuge den vector ohne Allocator. Da fählt mir wohl noch wissen mit diesen templates. Genau so subekt ist mir dieses InputIt.
-
Den
Allocator
kannst du weglassen (oder genauso übernehmen und deinem internenvector
übergeben).Und
InputIt
steht für einen beliebigen "input iterator", d.h. jeder Datentyp, der entsprechend [Legacy]InputIterator passende Funktionalität anbietet (u.a. auch ein passender Zeigertyp).In der C++ Standard Library gibt es einen Basisdatentyp für Iteratoren (ab C++17 jedoch
deprecated
): std::iterator.Die Funktionalität von Iteratoren bleibt jedoch gleich.
Als weitere Info noch (auch für Mitleser): std::iterator is deprecated: Why, What It Was, and What to Use Instead?
-
@Th69 sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":
Den Allocator kannst du weglassen (oder genauso übernehmen und deinem internen vector übergeben).
Und InputIt steht für einen beliebigen "input iterator", d.h. jeder Datentyp, der entsprechend [Legacy]InputIterator passende Funktionalität anbietet (u.a. auch ein passender Zeigertyp).
In der C++ Standard Library gibt es einen Basisdatentyp für Iteratoren (ab C++17 jedoch deprecated): std::iterator.
Die Funktionalität von Iteratoren bleibt jedoch gleich.
Als weitere Info noch (auch für Mitleser): std::iterator is deprecated: Why, What It Was, and What to Use Instead?Ok aber was ist der Allocator, dann wenn ich ihn einfach weglasse ? Er exeistiert dann einfach nicht oder wie ?
-
s. std::vector, d.h. es wird ein Default-Allocator (
std::allocator<T>
) benutzt, wenn man diesen Template-Parameter nicht angibt.
-
@Th69 sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":
s. std::vector, d.h. es wird ein Default-Allocator (std::allocator<T>) benutzt, wenn man diesen Template-Parameter nicht angibt.
Ach da steht die genau Definition.
template< class T, class Allocator = std::allocator<T> > class vector;
Ok kam jetzt nicht auf die Idee einfach in der header Datei zu gucken. Dachte im Referenz-link steht schon "alles" wichtige... Ok muss ich in Zukunft daran denken :D.
-
@martin_zi Natürlich steht das auch in der Referenz. Aber halt in dem Teil zum Template
std::vector
, nicht in dem Teil zu dessen speziellen Konstruktorstd::vector::vector
, der mit Templateargumenten überhaupt nichts zu tun hat:
https://en.cppreference.com/w/cpp/container/vectorIn Header zu gucken, solltest du dir lieber nicht angewöhnen, das ist nur unleserlich und nicht zielführend. Der Sprachstandard (den die Referenzen hoffentlich genau wiedergeben) legt fest, wie die Containerklassen aussehen. In die Header zu gucken ist nur dann angebracht, wenn du meinst einen Fehler in deiner ganz speziellen Implementierung gefunden zu haben.
-
@SeppJ sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":
@martin_zi Natürlich steht das auch in der Referenz. Aber halt in dem Teil zum Template std::vector, nicht in dem Teil zu dessen speziellen Konstruktor std::vector::vector, der mit Templateargumenten überhaupt nichts zu tun hat:
https://en.cppreference.com/w/cpp/container/vector
In Header zu gucken, solltest du dir lieber nicht angewöhnen, das ist nur unleserlich und nicht zielführend. Der Sprachstandard (den die Referenzen hoffentlich genau wiedergeben) legt fest, wie die Containerklassen aussehen. In die Header zu gucken ist nur dann angebracht, wenn du meinst einen Fehler in deiner ganz speziellen Implementierung gefunden zu haben.Ja ich habe erst jetzt so einigermaßen kapiert, wie man mit der Seite umgeht um sich dort zurechtzufinden. Und das man da oben herumglicken kann und nicht nur bei den links. Jetzt wirde für mich die Seite doch recht übersichtlich .
-
@martin_zi Ein allocator ist ein allgemeines Dingsti das Speicher besorgt. Ein iterator is ein allgemeines Dinsti das auf Speicher zeigt. Zeiger sind super iteratoren.