Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);"



  • @SeppJ sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":

    Häh? Was? Wozu? Welche Klasse? Wovon redest du? Womit hast du Schwierigkeiten? Wenn du Fragen stellst, dann denk daran, dass wir weder deinen Code kennen, noch in deinen Kopf gucken können.

    Hallo

    Es gibt noch keine Code weder im Kopf noch sonstwo, das ist ja meine Frage. 🙂

    Also anderes gefragt:

    class MyClass
    { 
    }
    
    int main(int argc, char** argv)
    {
       std::vector<std::string> myAllArgs(argv, argv + argc);
       for (auto argument : myAllArgs)
       {
          cout << argument << endl;
       }
        // ???????????????????????????????????? 
        std::vector<MyClass> myAllIrgendwas(argv, argv + argc); // wird nicht funktionieren.
    }
    

    Das wird nicht funktionieren. Also die Frage: Was muss ich tun damit ich das auch bei MyClass anwenden kann. Abgesehen davon das die "Typen" nicht zusammenpassen.

    Aber ich denke manni66 hat mir den wichtigen Hinweis schon gegeben und ich kann erstmal weiter probieren. Danke erstmal.

    Grüße



  • @martin_zi sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":

    Aber ich denke manni66 hat mir den wichtigen Hinweis schon gegeben

    Ja? Ich hatte angenommen, du woltest selber etwas in der Art von vector implementieren.

    Für std::vector<MyClass> muss deine Klasse einen Konstuktor mit char*, std::string oder auch std::string_view haben.



  • @manni66 sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":

    Ja? Ich hatte angenommen, du woltest selber etwas in der Art von vector implementieren.

    Irgendwie schon weil ich zumindest jetzt weiß wonach ich jetzt suchen muss. Und der nächste Schritt wäre auch gewesen dass ich die Art von vector implmentieren will. Sonst habe ich immer Probleme das zu verstehen.

    also:

       MyVector<MyClass>  std::vector<MyClass> myElements(elements, elements + 10);
    

    Für ersten Fall brauche ich aber keinen Konstruktor mit string. Das geht auch einfach so.

    class MyClass
    {
    public:
       MyClass()
       {
       }
       string sinnlos;
    };
    
    int main(int argc, char** argv)
    {
       MyClass elements[10];
       elements[0].sinnlos  = "0";
       elements[1].sinnlos  = "1"; 
       elements[2].sinnlos  = "2";
       elements[3].sinnlos  = "3";
       elements[4].sinnlos  = "4";
       elements[5].sinnlos  = "5";
       elements[6].sinnlos  = "6";
       elements[7].sinnlos  = "7";
       elements[8].sinnlos  = "8";
       elements[9].sinnlos  = "9";
    
       std::vector<MyClass> myElements(elements, elements + 10);
       for (auto argument : myElements)
       {
          cout << argument.sinnlos << endl;
        }
    }
    

    hmmmmmmmm dieses/er "Syntax" geht mir schon etwas zu schnell 🙂

    Aber damit wird es zumindestens klarer.

    vector( InputIt first, InputIt last,
            const Allocator& alloc = Allocator() );
    


  • Der Sinn deiner Knödelei lässt sich nicht erkennen. Der gleiche Effekt in kurz:

    #include <iostream>
    #include <string>
    #include <iterator>
    
    using namespace std;
    
    class MyClass
    {
    public:
       string sinnlos;
    };
    
    int main(int argc, char** argv)
    {
       MyClass elements[] = {"0", "1", "2", "3" };
    
       for (auto& argument : elements)
       {
          cout << argument.sinnlos << endl;
        }
    }
    


  • @manni66 sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":

    Der Sinn deiner Knödelei lässt sich nicht erkennen. Der gleiche Effekt in kurz:

    ÄÄ ja natürlich geht das auch kürzer. 🙂

    Es geht nur um diese Zeile die mir tausend Fragen aufwirft:

       std::vector<MyClass> myElements(elements, elements + 10);
    

    Alles anderes ist das drumherum. Der Sinn ist, versuchen zu verstehen was die Zeile genau macht und warum das überhaupt compilierbar ist. Und der Compiler nicht sagt. "Syntax Error myElements is not defined" oder sowas.



  • @manni66 sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":

    MyClass elements[] = {"0", "1", "2", "3" };

    momentmal das ist doch gar nicht kompilierbar das geht doch nur wenn ich MyClass (std::initializer_list<int> list) implementiert habe ... 🤔



  • @martin_zi sagte in Was mache ich hier ? "std::vector<std::string> myAllArgs(argv, argv + argc);":

    MyClass elements[] = {"0", "1", "2", "3" };

    momentmal das ist doch gar nicht kompilierbar das geht doch nur wenn ich MyClass (std::initializer_list<int> list) implementiert habe ...

    Hast du das [] nach elements gesehen?



  • @hustbaer 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);":

    MyClass elements[] = {"0", "1", "2", "3" };

    momentmal das ist doch gar nicht kompilierbar das geht doch nur wenn ich MyClass (std::initializer_list<int> list) implementiert habe ...

    Hast du das [] nach elements gesehen?

    Ja und mein compiler mag das nicht: "error: conversion from 'const char [2]' to non-scalar type 'MyClass' requested"

    class MyClass
    {
    public:
       MyClass()
       {
       }
       sinnlos = myString;
    };
    
    int main(int argc, char** argv)
    {
       MyClass elements[] = {"0", "1", "2", "3" };
       return 0;
    }
    

    Das feature funktioniert doch auch nur wenn die Klasse das implementiert hat. 🤔



  • @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.



  • @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 ein Foo braucht, und Foo ist mit einem std::string erzeugbar, und der std::string ist mit einem const 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 einem MyClass Array müssen die Werte innerhalb der {} also geeignet sein MyClass Objekte zu initialisieren. D.h. {"a", "b"} ist vergleichbar mit takeFoo("blah") im Beispiel oben, geht also nicht.

    Bei {{"a"}, {"b"}} dagegen werden {"a"} und {"b"} als Initialisierung eines std::string verstanden, und dann kann mit nur einer "user defined conversion" ein MyClass 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 ? 🙂


Anmelden zum Antworten