objekte aus parameter pack erstellen



  • Ich steh gerade auf dem schlauch, ich will sowas wie:

    #include <vector>
    
    struct Aware {};
    struct Aware1 : public Aware {};
    struct Aware2 : public Aware {};
    
    template<typename... Params>
    class Material
    {
    public:
    	Material()
    	{
    		Push<Params...>();
    	}
    
    	template<typename... Params>
    	void Push()
    	{
    		// call Add<T>() für jedes argument
    		// bzw irgendwie die objekte aus dem pack erstellen
    	}
    private:
    	template<typename T>
    	void Add()
    	{
    		awares.push_back(new T());
    	}
    
    	std::vector<Aware*> awares;
    };
    
    int main() 
    {
    	Material<Aware1, Aware2> mat;
    }
    

    kriegs leider nicht hin 😞



  • Erstens scheint es mir nicht sinnvoll, aus Material ein Template zu machen, wenn du die Elemente sowieso abstrakt speicherst. Mit statischer Typinformation kannst du gleich ein effizienteres std::tuple nehmen. Ich würde also eher eine Typliste an den Konstruktor übergeben.

    Durch die Typen im Parameter-Pack iterieren kannst du mittels Rekursion. Schau dir z.B. mal das Beispiel hier an.



  • Du kannst auch den Array-Trick nutzen:

    template<typename... Params>
    void Push()
    {
      char arr[] = {(Add<Param>(), 0)...};
    }
    

    Aber nicht ganz sinnvoll ist es trotzdem.



  • Nathan schrieb:

    Du kannst auch den Array-Trick nutzen:

    template<typename... Params>
    void Push()
    {
      char arr[] = {(Add<Param>(), 0)...};
    }
    

    Aber nicht ganz sinnvoll ist es trotzdem.

    Danke das funktioniert super 🙂 Könntest du vielleicht noch erläuftern was genau da passiert? mir erschließt sich das noch nicht. vorallem

    (Add<Param>(), 0)
    

    Er versucht das paramter pack zu expanden, aber wieso ",0" ?

    Ps. Ja vielleicht nicht ganz sinnvoll aber ich bin eh nur am rumspielen 🙂



  • Komma-Operator.
    In einer Array-Initialisierung kann man packs so ausrollen.
    Allerdings muss der Ausdruck einen gültigen Wert zurückliefern, mit dem das Array befüllt werden kann. Deine Funktion liefert void zurück, also nutze ich den Komma-Operator um das Arrayelement anschließend mit 0 zu initialisieren.



  • 👍 Macht sinn, danke 🙂

    Ps. habs jetzt in anlehnung an nexus so gemacht 🙂

    #include <vector>
    #include <utility>
    #include <memory>
    
    struct Aware { int a; };
    struct Aware1 : public Aware { int b; };
    struct Aware2 : public Aware { int c; };
    
    class Material
    {
    public:
    	template<class... Types>
    	Material(Types&&... args)
    	{
    		Add<Types...>(std::forward<Types>(args)...);
    	}
    
    private:
    	template<typename Elem, typename... Types>
    	void Add(Elem&& elem, Types&&... args)
    	{
    		awares.push_back(std::move(elem));
    		Add(std::forward<Types>(args)...);
    	}
    
    	template<typename Elem>
    	void Add(Elem&& elem)
    	{
    		awares.push_back(std::move(elem));
    	}
    
    	template<typename... Types>
    	void Add(){}
    
    	std::vector<std::unique_ptr<Aware>> awares;
    };
    
    int main() 
    {
    	Material mat(std::make_unique<Aware1>());
    }
    

Anmelden zum Antworten