datentyp clonen



  • Kann ich irgendwie einen Datentyp erstellen, der sich genau wie ein anderer verhält, aber den anderen als member hat?
    Sie soll die auszuführenden Operationen also nicht auf sich selbst ausführen sondern auf der durch den Template-Parameter angegebenen Klasse, von der sie eine Referenz gespeichert hat...

    Was ich in etwa möchte, ist evtl am besten/einfachsten mit nem Stück Code zu zeigen:

    template<typename TAlloc>
    class alloc_wrapper
    {
    public:
    	typedef typename TAlloc::value_type              value_type;
    
    	typedef typename TAlloc::pointer                    pointer;
    	typedef typename TAlloc::const_pointer        const_pointer;
    	typedef typename TAlloc::reference                reference;
    	typedef typename TAlloc::const_reference    const_reference;
    
    	typedef typename TAlloc::difference_type    difference_type;
    	typedef typename TAlloc::size_type                size_type;
    
    	template<typename U>
    	struct rebind
    	{
    		alloc_wrapper< TAlloc::rebind<U> > other;
    	};
    
    	alloc_wrapper(TAlloc &tmp)
    	:	myself(&tmp)
    	{}
    
    	alloc_wrapper(const alloc_wrapper&) {/**/}
    	alloc_wrapper& operator= (const alloc_wrapper &) {/**/}
    
    //hier sollen alle alloc_wrapper funktionen bereit gestellt sein, die immer so hier ausgeführt werden:
    
    	T foo(U u, V v)
    	{
    		return myself->foo(u, v);
    	}
    private:
    	TAlloc *myself; //swappable reference
    };
    

    Falls das nicht geht, würde ich den Allocator wohl nur mit den, im Standard festgelegten, Funktionen implementieren und eben ein wenig tippen müssen...

    bb


  • Mod

    Wie soll das mit dem rebind funktionieren ohne Defaultkonstruktor?
    Ultimativ glaube ich nicht, dass es möglich ist, string mittels eines anderen Standardcontainers (außer vector) sinnvoll zu implementieren.


  • Mod

    Was ich mir vorstellen könnte: Du benutzt deine Klasse wie einen Zeiger und überlädst die Dereferenzierungsoperatoren so, dass sie auf den Datamember verweisen.



  • Was spricht gegen eine Ableitung? Also sowas wie

    template<class TAlloc> class alloc_wrapper : public TAlloc { ... };
    

  • Mod

    XMaster schrieb:

    Was spricht gegen eine Ableitung?

    Die Tatsache, dass das eigentliche Allokatorobjekt nicht im Wrapper selbst gespeichert sein soll.



  • camper schrieb:

    Wie soll das mit dem rebind funktionieren ohne Defaultkonstruktor?

    Imho brauch man den nie...

    camper schrieb:

    Ultimativ glaube ich nicht, dass es möglich ist, string mittels eines anderen Standardcontainers (außer vector) sinnvoll zu implementieren.

    Ich denke schon - wenn ich das mit dem allocator iwie hinbekommen habe, dann bin ich eigtl fertig - die einzige einschränkung wäre dann, dass compare nicht die traits_type::compare fkt nutzt - aber das wäre ohne weiteres möglich (nur performace-technisch eher doof^^)

    bb

    @SeppJ:
    Ne, man soll ihn noch ganz normal verwenden können - wie immer halt... Evtl gehts mit nem konvertierungsoperator - ich test es aber erst mal mit dem wrappen der standard-funktionen und dann mal gucken, ob es auch noch schöner geht^^

    @XMaster:
    Das die Operationen auf einer anderen Instanz abgewickelt werden sollen...


  • Mod

    Ohne Defaultkonstruktor kann ein Container keine Allokatoren für andere Typen erstellen. Container, die keine anderen Allokatoren benötigen, gibt es nicht viele. Abgesehen von vector dürften praktisch alle anderen Standardcontainer etwas anderes als den übergebenen Allokator verwenden.



  • camper schrieb:

    Ohne Defaultkonstruktor kann ein Container keine Allokatoren für andere Typen erstellen. Container, die keine anderen Allokatoren benötigen, gibt es nicht viele. Abgesehen von vector dürften praktisch alle anderen Standardcontainer etwas anderes als den übergebenen Allokator verwenden.

    Ich dachte immer, dass das per copy-ctor gemacht wird!?

    template< typename T, typename A>
    struct container
    {
      struct node;
      typedef A::rebind<node> Tmy_alloc;
    
      container(const A &_my_alloc) : my_alloc(_my_alloc) {}
    
      Tmy_alloc my_alloc;
    };
    

    !?

    bb


  • Mod

    unskilled schrieb:

    Ich dachte immer, dass das per copy-ctor gemacht wird!?

    Und was hat der Typ A mit A::rebind<node>::other zu tun?



  • camper schrieb:

    unskilled schrieb:

    Ich dachte immer, dass das per copy-ctor gemacht wird!?

    Und was hat der Typ A mit A::rebind<node>::other zu tun?

    das der allocator auf den node-typ rebinded wird? Oo
    allerdings so:
    typedef typename A::rebind<node>::other Tmy_alloc;

    bb


  • Mod

    unskilled schrieb:

    camper schrieb:

    unskilled schrieb:

    Ich dachte immer, dass das per copy-ctor gemacht wird!?

    Und was hat der Typ A mit A::rebind<node>::other zu tun?

    das der allocator auf den node-typ rebinded wird? Oo
    allerdings so:
    typedef typename A::rebind<node>::other Tmy_alloc;

    bb

    Stimmt. Aber es sind verschiedene Typen, oder? Wie willst du sie dann mittels Copyctor kopieren?



  • hmm... bis vorhin dachte ich noch, dass ich da bissl wild rumcasten kann, da weder ctor noch dtor aufgerufen werden müssen, weil eh alles nur Zeichen sind, aber die nodes brauchen ja trotzdem nen ctor/dtor - ma gucken, ob mir irgendwann mal noch was anderes einfällt : D

    bb

    eidt: Es würde aber gehen, wenn man an den Container-Allokator rankommen würde^^ Leider wird es da keinen Standard-konformen Weg geben 😕



  • camper schrieb:

    Ultimativ glaube ich nicht, dass es möglich ist, string mittels eines anderen Standardcontainers (außer vector) sinnvoll zu implementieren.

    Japp - nach stundenlangem Probieren, denk ich jetzt auch so darüber^^

    Ich hab mich einfach ein wenig vom standard entfernt und c_str() und data() nicht als member-fkt angeboten (was den weiteren nachteil hat, dass man keinen allocator anbieten kann - wobei das ohne weiteres möglich sein sollte - muss man nur noch mal allocator und laenge in der hilfs-klasse speichern)

    template <typename C>
    struct c_str_ptr
    {
    private:
    	const C *data;
    
    	c_str_ptr(const c_str_ptr&);
    	c_str_ptr& operator= (const c_str_ptr&);
    public:
    	c_str_ptr(const C *_data) : data(_data) {}
    	~c_str_ptr() {delete []data;}
    
    	operator const C*() {return data;}
    };
    
    template<typename C, typename T, typename A, template <typename, typename> class V>
    c_str_ptr<C> c_str(const my::basic_string<C, T, A, V> &these)
    {
    	C* R = new C[these.size()+1];
    	std::copy(these.begin(), these.end(), R);
    	R[these.size()] = C();
    	return R;
    }
    
    template<typename C, typename T, typename A, template <typename, typename> class V>
    c_str_ptr<C> data(const my::basic_string<C, T, A, V> &these)
    {
    	C* R = new C[these.size()];
    	std::copy(these.begin(), these.end(), R);
    	return R;
    }
    

    bb

    edit: op const char* -> op const C*



  • unskilled schrieb:

    C *data;
    // ...
    	operator const char*() {return data;}
    

    wäre nicht operator const C*() besser?



  • XMaster schrieb:

    unskilled schrieb:

    C *data;
    // ...
    	operator const char*() {return data;}
    

    wäre nicht operator const C*() besser?

    oh, ja - sicher
    danke : >
    habs ma editiert


Anmelden zum Antworten