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>());
    }
    

Log in to reply