Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

20.07.2012, 00:17

Spezialisierte Funktion Templates

Guten Abend ich hab schon wieder ein Problem mit meinem kleinen Test Programm. Ich möchte einige Pointer zu DX Objecten in einem vector speichern. In meinem Helper wollte ich mir eine Funktion schreiben die einen vector<IUnknown> annimmt und dann für alle Objecte Release aufruft.

Bei der "template <typename T = IUnknown>" Variante bekomme ich einen C4519-Fehler und die Variante dürfte mit einer Funktion nicht funktionieren.
Ich habe auch schon versucht die Funktion als Parameter einen vector<IUnknown> annehmen zu lassen (ohne die Funktion zu templateisieren(ist das überhaupt ein echtes Wort?)) allerdings kommt dann der Fehler das von der abstrakten Klasse IUknown keine Instanz erstellt werden kann. Da ich sowieso nur Pointer in dem vector habe habe ich dann auch vector<IUnknown*> versucht allerdings möchte er meinen vector nicht in vector<InUknown*> casten obwohl die Elemente in meinem vector alle von IUnknown erben. Jemand eine Idee was ich machen muss damit die Funktion möglichst jeden vector<"von IUnknown erbender Typ"> annimmt?
greate minds discuss ideas;
average minds discuss events;
small minds discuss people.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

20.07.2012, 00:56

Mach einfach einen std::vector<com_ptr<Whatever>> ;)
Ansonsten wärs gut, dein Problem vielleicht mit etwas Code zu illustrieren.
Und abgesehen davon, will man meistens eigentlich eher Overloading statt tatsächlich eine Spezialisierung: http://www.gotw.ca/publications/mill17.htm

3

20.07.2012, 03:55

Ich war mir nicht sicher ob es sinnvoll ist die fehlerhafte Funktion zu posten aber hier mal die 3 Versionen aus dem ersten Post.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// Version 1
    template<class T = IUnknown>
    void ReleaseComVector( std::vector< T > &vVector )
    {
        std::vector< T >::iterator iter = vVector.begin();
        std::vector< T >::iterator end = vVector.end();
        
        while(iter != end)
        {
            (*iter)->Release();
            iter++;
        }

        vVector.clear();
    }

// Version 2
    void ReleaseComVector( std::vector< IUnknown > &vVector )
    {
        std::vector< IUnknown >::iterator iter = vVector.begin();
        std::vector< IUnknown >::iterator end = vVector.end();
        
        while(iter != end)
        {
            (*iter)->Release();
            iter++;
        }

        vVector.clear();
    }

// Version 3
void ReleaseComVector( std::vector< IUnknown* > &vVector )
    {
        std::vector< IUnknown* >::iterator iter = vVector.begin();
        std::vector< IUnknown* >::iterator end = vVector.end();
        
        while(iter != end)
        {
            (*iter)->Release();
            iter++;
        }

        vVector.clear();
    }


Und die gleiche Funktion mal in C# umgesetzt allerdings mit einer List statt Vector:

C#-Quelltext

1
2
3
4
5
6
7
8
void ReleaseComVector<T>(List<T> list) where T : IUnknown
{
    foreach(IUnknown comObj in list)
    {
        comObj.Release();
    }
    list.clear();
}


Mach einfach einen std::vector<com_ptr<Whatever>> ;)

Das würde ja auch nur funktionieren wenn der com_ptr aufjedenfall nur IUnknown Objekte/Pointer nimmt um dann im destruktor Release() aufzurufen oder nicht?
greate minds discuss ideas;
average minds discuss events;
small minds discuss people.

idontknow

unregistriert

4

20.07.2012, 09:36

was willst du mit dem IUnknown erreichen? Wäre mir neu, dass es sowas gibt bzw das klappt, kann aber gut sein ich bezweifel nur irgendwie, dass es das ist was du willst.

Lass das mit dem "= IUnkown" einfach weg, dann muesste alles funktionieren denke ich.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

5

20.07.2012, 09:57

Wie du schon rausgefunden hast, brauchst du ein IUnknown*, da IUnknown ein Interface und damit abstrakt ist und nicht instanziert werden kann (es gibt in C++ keine Unterscheidung zwischen Werttypen und Referenztypen; wenn du eine Referenz willst, dann musst du das explizit deklarieren).
Was genau das Problem mit dem com_ptr ist, hab ich nicht so ganz verstanden.

CodingCat

1x Contest-Sieger

Beiträge: 420

Beruf: Student (KIT)

  • Private Nachricht senden

6

20.07.2012, 12:04

Mach einfach einen std::vector<com_ptr<Whatever>> ;)

Das würde ja auch nur funktionieren wenn der com_ptr aufjedenfall nur IUnknown Objekte/Pointer nimmt um dann im destruktor Release() aufzurufen oder nicht?

Nein, Templates funktionieren anders als Generics. Ein Template wird für jeden gegebenen Typ neu instantiiert, das heißt, für jeden gegebenen Typ erzeugt der Compiler eigenen Code, in dem ein Template-Parameter nicht durch eine gemeinsame Typschranke, sondern tatsächlich den vollständigen übergebenen Typ ersetzt wird. Instantiierst du nun einen com_ptr<IAdapter>, wie im anderen Thread, dann wird der Template-Parameter T in dieser Instanz nicht zu IUnknown, sondern tatsächlich zu IAdapter. Ein com_ptr<IDevice> würde dagegen anderen Code erzeugen, in dem der Template-Parameter T tatsächlich IDevice wäre. Da beide Typen von IUnknown erben, lässt sich trotzdem für beide im Destruktor Release() aufrufen, beide rufen aber grundsätzlich unterschiedliche com_ptr-Destruktoren auf, wenngleich das in diesem Fall keinen Unterschied macht. Würdest du com_ptr<Foo> instantiieren, ohne dass Foo eine Release()-Methode anbietet, dann würdest du für den com_ptr-Destruktor dieser Instantiierung natürlich einen Compiler-Fehler erhalten.

(Nebensächliche Anmerkung: Erzeugen verschiedene Template-Instantiierungen identischen Code, so verschmilzt der Compiler diesen bei der Optimierung wieder. Das hat keine Auswirkung auf das Programmverhalten, verhindert aber ein Explodieren der Programmgröße.)

Vektoren von com_ptr<IIrgendeinD3DInterface> kannst du auf jeden Fall problemlos anlegen, und musst dann auch keine Funktionen mit Schleifen zum Aufräumen mehr schreiben, weil bei Zerstörung des Vektors automatisch alle enthaltenen com_ptrs zerstört werden, und damit automatisch für alle enthaltenen COM-Zeiger Release() aufgerufen wird.
alphanew.net (last updated 2011-06-26) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »CodingCat« (20.07.2012, 12:14)


Werbeanzeige