STL Vector, operator=(..) überladen, kein const Argument



  • Hi,
    hoffentlich könnt ihr mir weiter helfen 🙂
    Folgendes Problem:
    Ich erstelle zunächst einen Vector:

    std::vector<Campaign>* list = new std::vector<Campaign>;

    Nun möchte ich Folgendes aufrufen:

    list->operator=(result->return_);

    wobei result->return_ den von gSOAP erstellten Typ std::vector<xsd__anyType * > hat. (Ist aber für mein Problem vermutlich nicht wichtig,siehe Compiler-Fehlermeldung)

    Der Compiler gibt mir folgende Fehlermeldung aus:

    helloworld.cpp(167) : error C2664: 'std::vector<_Ty>::operator =': Konvertierung des Parameters 1 von 'std::vector<_Ty>' in 'const std::vector<_Ty> &' nicht möglich
    with
    [
    _Ty=Campaign
    ]
    and
    [
    _Ty=xsd__anyType *
    ]
    and
    [
    _Ty=Campaign
    ]
    Ursache: Konvertierung von 'std::vector<_Ty>' in 'const std::vector<_Ty>' nicht möglich
    with
    [
    _Ty=xsd__anyType *
    ]
    and
    [
    _Ty=Campaign
    ]
    Kein benutzerdefinierter Konvertierungsoperator verfügbar, der diese Konvertierung durchführen kann, oder der Operator kann nicht aufgerufen werden

    anscheinend liegt es daran das result->return_ nicht const ist, aber die Funktion operator=(...) ein const Argument erwartet.
    Wo ( in der Klasse campaign?, in der hellworld.cpp?) und wie müsste ich den Operator=(..) überschreiben sodass kopieren auch ohne const Argument möglich ist?

    Danke schon mal für jegliche Hilfe/Idee,
    Grüße,
    Christoph


  • Administrator

    1. Das Problem liegt daran, dass du einem std::vector mit Campaign Objekten einen std::vector voller xsd__anyType* Objekte zuweisen willst. Ganz ehrlich, wie soll das gehen?
    2. Wieso erstellst du den std::vector<Campaign> per new ?

    Grüssli



  • Was ist überhaupt das hier für ein Käse: list->operator=(result->return_);

    std::vector< xsd__anyType* > vec = result->return_; // ist return_ etwa ein private member? Wenn ja, dann vergiss es das das überhaupt funktioniert
    

    Mit const hat das in Deinem Fall überhaupt nichts zu tun. Wenn eine Funktion/Methode einen const Parameter definiert heist das nur das innerhalb dieser Funktion/Methode: das Object/die Referenz auf das Objekt/ein Zeiger auf das Objekt nicht verändert werden kann oder brauch.

    Gut Schuß
    VuuRWerK 😉



  • result->return_ ist der Rückgabewert einer Funktion eines Webservice (in Java gecodet). Diese Funktion gibt eine java.util.list zurück, also eine ganz normale Liste von Objekten "campaign". Die Liste möchte in einem c++ Projekt weiter verwenden, deshalb möchte ich die Liste in einen stl vector kopieren.
    Der Typ xsd__anyType* wurde von gSOAP automatisch erstellt, praktisch als Platzhalter für den jeweiligen Objekttyp.
    Aber anscheinend ist das Problem wohl doch kein reines c++ Problem.
    Aber vielleicht kennt sich ja trotzdem jemand zufällig mit gSOAP aus und weiß Rat 🙂



  • Die Funktion gibt innerhalb deines Webservices eine java.util.list zurück. Das SOAP Framework in java macht daraus einen XML-String und schickt den übers Netz an deine Applikation. gSOAP wandelt diesen XML-String wiederum in Daten. Wie diese Daten dann aussehen entnimmst du am Besten der gSOAP-Doku. Ein std::vector kommt da jedenfalls nicht ohne weiteres bei raus.



  • Du hast doch selbst gesagt, der Vector ist vom Typ vector<xsd__anyType*> (das macht gSOAP aus dieser XML-Liste, die wie pumuckl richtig gesagt hat nichts mehr mit der Java-Liste zu tun hat). Diesen möchtest Du in einen vector<Campaign> umwandeln. Dazu musst Du jedes einzelne Element von xsd__anyType* in Campaign umwandeln. Woher soll der Compiler wissen, wie das geht?

    Soweit ich gSOAP kenne, ist "Campaign" nichtmal eine der generierten Klassen, so dass gSOAP kein Bewusstsein über "Campaign" hat, oder?

    Denkbar wäre z.B:

    Campaign anyToCampaign( xsd__anyType const* wert )
    {
        /* unwandeln */
    }
    
    std::vector< Campaign > list( result->return_.size() );
    std::transform( result->return_.begin(), result->return_.end(), list.begin(), anyToCampaign );
    


  • Hi,
    mein obiger Post war etwas blöd formuliert. Der von gSOAP erstellte Typ ist ns1__campaign, wir benutzen aber in dem c++ Programm eine Klasse Campaign welche als Attribut einen Zeiger auf ein ns1__campaign enthält, deshalb stand oben std::vector<Campaign> und nicht std::vector<ns1__campaign>.
    Lieber arbeite ich nur mit ns1__campaign und dafür funktioniert das ganze.
    Ich habe nun den Code von LordJaxom übernommen, aber wenn ich ehrlich bin weiß ich nicht wirklich wie ich Funktion anytoCampaign coden soll.
    Momentan sieht es so aus (mit ns1__campaign anstatt Campaign):

    ns1__campaign anyToCampaign( xsd__anyType const* wert )
    {
    /* unwandeln */

    }

    std::vector<ns1__campaign> list( result->return_.size() );
    std::transform( result->return_.begin(), result->return_.end(), list.begin(), anyToCampaign );

    Ich hoffe folgender von gSOAP erstellter Code ist hilfreich:

    ifndef SOAP_TYPE_ns1__campaign
    #define SOAP_TYPE_ns1__campaign (21)
    /* ns1:campaign */
    class SOAP_CMAC ns1__campaign : public xsd__anyType
    {
    public:
    	int *bonus;	/* optional element of type xsd:int */
    	std::string *description;	/* optional element of type xsd:string */
    	std::string *happyEnd;	/* optional element of type xsd:string */
    	int *id;	/* optional element of type xsd:int */
    	bool isSorted;	/* required element of type xsd:boolean */
    	int modus;	/* required element of type xsd:int */
    	std::string *name;	/* optional element of type xsd:string */
    	int rateCount;	/* required element of type xsd:int */
    	int rateSum;	/* required element of type xsd:int */
    	int *type;	/* optional element of type xsd:int */
    public:
    	virtual int soap_type() const { return 21; } /* = unique id SOAP_TYPE_ns1__campaign */
    	virtual void soap_default(struct soap*);
    	virtual void soap_serialize(struct soap*) const;
    	virtual int soap_put(struct soap*, const char*, const char*) const;
    	virtual int soap_out(struct soap*, const char*, int, const char*) const;
    	virtual void *soap_get(struct soap*, const char*, const char*);
    	virtual void *soap_in(struct soap*, const char*, const char*);
    	         ns1__campaign() : bonus(NULL), description(NULL), happyEnd(NULL), id(NULL), isSorted((bool)0), modus(0), name(NULL), rateCount(0), rateSum(0), type(NULL) { }
    	virtual ~ns1__campaign() { }
    };
    #endif
    
    class SOAP_CMAC ns1__loadCampaignsResponse : public xsd__anyType
    {
    public:
    	std::vector<xsd__anyType * >return_;	/* SOAP 1.2 RPC return element (when namespace qualified) */	/* optional element of type xsd:anyType */
    public:
    	virtual int soap_type() const { return 25; } /* = unique id SOAP_TYPE_ns1__loadCampaignsResponse */
    	virtual void soap_default(struct soap*);
    	virtual void soap_serialize(struct soap*) const;
    	virtual int soap_put(struct soap*, const char*, const char*) const;
    	virtual int soap_out(struct soap*, const char*, int, const char*) const;
    	virtual void *soap_get(struct soap*, const char*, const char*);
    	virtual void *soap_in(struct soap*, const char*, const char*);
    	         ns1__loadCampaignsResponse()  { }
    	virtual ~ns1__loadCampaignsResponse() { }
    };
    #endif
    

    Danke für die Hilfe bisher,
    Christoph



  • In diesem Fall gehe ich davon aus, dass die Objekte in dem anyType-Vector alle vom (dynamischen) Typ ns1__Campaign sind (sofern im XML dort wirklich keine Elemente anderen Typs stehen), da xsd_anyType polymorph ist und ns1__Campain von xsd_anyType erbt. Damit kannst Du eine(n) Zeiger/Referenz auf ein xsd__anyType-Element dynamisch auf eine(n) Zeiger/Referenz auf ein ns1__Campaign casten (mit dynamic_cast). Wenn Du Zeiger so castest gibt es 0 zurück, wenn ein Element nicht vom geforderten Typ ist, bei Referenzen fliegt eine Exception.

    Die Umwandlungsfunktion müsste natürlich dann einen Zeiger zurückgeben, der Vorteil wäre zunächst mal dass keine Daten kopiert werden müssten. Aber nach dem gleichen Prinzip kannst Du dann auch Dein Campaign-Objekt erstellen.

    ns1__campaign* anyToCampaign( xsd__anyType* wert ) /* anmerkung: dieses mal müssen entweder beide Objekte const sein oder keins von beiden */
    { 
       return &dynamic_cast<ns1__campaign&>(*wert);
       // wegen des oben beschriebenen Verhaltens des Referenzcasts sieht dieser etwas kryptisch aus, da ich eine exception möchte, falls ein wert kein ns1__campaign ist.
    }
    
    std::vector<ns1__campaign*> list( result->return_.size() ); 
    try {
       std::transform( result->return_.begin(), result->return_.end(), list.begin(), anyToCampaign );
    } catch (std::bad_cast const&) {
       std::cout << "unerwartete xml-elemente!";
    }
    

    oder

    Campaign anyToCampaign( xsd__anyType* wert ) 
    { 
       return Campaign( &dynamic_cast<ns1__campaign&>(*wert) );
    }
    


  • Hi,
    vielen Dank, es hat nun geklappt 🙂


Anmelden zum Antworten