Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jul 04, 2025 04:07

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: C++ Templates eine Methode
BeitragVerfasst: Di Mai 08, 2012 08:14 
Offline
DGL Member

Registriert: Mi Okt 16, 2002 15:06
Beiträge: 1012
Servus,

ich möchte bei einer Methode einer Klasse eine Generischen Typ angeben lassen, geht das mit templates?
Hab leider noch nichts mit Template gemacht :(

Habe 3 Klassen:

Code:
  1. class CContent {
  2.   ...
  3. };
  4.  
  5. class CTexture : public CContent {
  6.   ...
  7. }
  8.  
  9. class CContentManager {
  10. public:
  11.   CContent* Load(std::string path);
  12. };


Ich möchte diese klasse irgendwie so erweitern:

Code:
  1. ]class CContentManager {
  2. public:
  3.   T Load<T as base type CContent*>(std::string path);
  4. };


und dann ungefähr so aufrufen...

Code:
  1. CContentManager* cman = new CContentManager();
  2. CTexture* myTexture = cman->Load<CTexture>("meine texture");


Ist das möglich? Das will ich machen, da ich denke das es die konfortablste Art ist, wie man entsprechende Assets lädt.
Sprich wenn ich CTexture als T verwende, dann werden intern nur nach Texture Loader gesucht usw.

Oder gibts da ne einfache lösung?
Was ich nicht will ist: cman->LoadTexture("meine texture");
Dann muss ich für jeden Content Typ eine eigene Load Methode aufrufen, aber ich hätte das System gern Generisch damit man es auch erweitern kann ^^


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: C++ Templates eine Methode
BeitragVerfasst: Di Mai 08, 2012 11:53 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2623
Wohnort: Berlin
Programmiersprache: Go, C/C++
Code:
  1. class CContentManager
  2. {
  3.   public:
  4.     template<typename T>
  5.     static T* Load(const std::string& RessourcePath){return 0;}
  6.   private:
  7.     static inline bool CommonLoadLogic(const std::string& RessourcePath, char*& buf, int& BufLen){
  8.       // file io code
  9.     }
  10. };
  11.  
  12. template<>
  13. CTexture* CContentManager::Load<CTexture>(const std::string& RessourcePath)
  14. {  
  15.   CTexture* result=0;
  16.   char* buf=0;
  17.   int buflen=0;
  18.   if (CommonLoadLogic(RessourcePath,buf,buflen))
  19.   {
  20.     result=new CTexture(buf,buflen);
  21.     // do some CTexture specific stuff
  22.   }
  23.   return result;
  24. }
  25.  
  26. template<>
  27. CMesh* CContentManager::Load<CMesh>(const std::string& RessourcePath)
  28. {  
  29.   CMesh* result=0;
  30.   char* buf=0;
  31.   int buflen=0;
  32.   if (CommonLoadLogic(RessourcePath,buf,buflen))
  33.   {
  34.     result=new CMesh(buf,buflen);
  35.     // do some CMeshspecific stuff
  36.   }
  37.   return result;
  38. }


Nicht getestet aber sollte so eigentlich nahezu kompilierbar sein.
Wichtig ist, dass man bei Spezialisierung einmal den undefinierten Fall hat, im CContentManager mit T und dann die Spezialisierten Fälle ohne template informationen zusätzlich angibt.
In dem Beispiel würden alle Möglichkeiten, außer CMesh und CTexture 0 zurück geben.

Die Sache hab ich mal als static definiert, da solche funktionen in der Regel keine Instanz benötigen und dem Factory Pattern entspricht.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: C++ Templates eine Methode
BeitragVerfasst: Di Mai 08, 2012 12:01 
Offline
DGL Member

Registriert: Mi Okt 16, 2002 15:06
Beiträge: 1012
Yay, Herzlichen Dank.
Werd das ganze gleich mal ausprobieren ^^


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: C++ Templates eine Methode
BeitragVerfasst: Di Mai 08, 2012 12:41 
Offline
DGL Member

Registriert: Mi Okt 16, 2002 15:06
Beiträge: 1012
Hmm, also es kompiliert irgendwie nicht. Hast ne idee? Fehler:

Error 2 error LNK1169: one or more multiply defined symbols found D:\Development\SFMLTest\GameFramework\Debug\GameFrameworkApp.exe 1 1 GameFrameworkApp

Error 1 error LNK2005: "public: class gf::CTexture2D * __thiscall gf::CContentManager::Load<class gf::CTexture2D>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??$Load@VCTexture2D@gf@@@CContentManager@gf@@QAEPAVCTexture2D@1@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in ContentManager.obj D:\Development\SFMLTest\GameFramework\GameFrameworkApp\TestGame.obj GameFrameworkApp

Fehler kommt erst sobald ich diese Load Methode verwende:

Code:
  1.    
  2. CTexture2D* tex = ContentManager()->Load<gf::CTexture2D>("mouses.jpg");
  3.  


Habs bei mir nicht static!

Code:
  1.    
  2. // header
  3.  
  4. class CContentManager
  5.     {
  6.     private:
  7.         std::string contentPath;
  8.         CGraphicsDevice* graphicDevice;
  9.         std::map<ContentType::Type, TExtensionContentLoaderMap> contentLoadersMap;
  10.         std::vector<CContentLoader*> contentLoaders;
  11.         bool LoadToBuffer(const std::string &name, char*& buf, int &bufLen);
  12.     public:
  13.         CContentManager(const std::string &contentPath, CGraphicsDevice* graphicDevice);
  14.         ~CContentManager(void);
  15.         inline const std::string& GetContentPath() { return this->contentPath; };
  16.         void AddContentLoader(const ContentType::Type &type, CContentLoader* loaderInstance);
  17.         template<typename T>
  18.         T* Load(const std::string &name) { return 0; };
  19.     };
  20.  
  21. // cpp
  22.  
  23.     bool CContentManager::LoadToBuffer(const std::string &name, char*& buf, int &bufLen)
  24.     {
  25.         std::string filename = IO::Path::Combine(contentPath, name);
  26.         std::string fileext = IO::Path::GetExtension(filename);
  27.         std::ifstream fileStream;
  28.         fileStream.open(filename.c_str(), std::ios::in | std::ios::binary);
  29.         if (fileStream.is_open()) {
  30.             std::istream::pos_type l = fileStream.tellg();
  31.             bufLen = static_cast<int>(l);
  32.             char* newbuf = (char*)malloc(bufLen);
  33.             fileStream.read(newbuf, bufLen);
  34.             return true;
  35.         }
  36.         return false;
  37.     }
  38.     template<>
  39.     CTexture2D* CContentManager::Load<CTexture2D>(const std::string &name) {
  40.         CTexture2D* res = 0;
  41.         char* buf=0;
  42.         int buflen=0;
  43.         if (LoadToBuffer(name, buf, buflen)) {
  44.             free(buf);
  45.         }
  46.         return res;
  47.     }
  48.  
  49.  


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: C++ Templates eine Methode
BeitragVerfasst: Di Mai 08, 2012 13:07 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2105
Wohnort: Vancouver, Canada
Programmiersprache: C++, Python
Mach mal ein #ifdef drumrum:

Code:
  1. #ifndef _MY_SUPER_TEMPLATE
  2. #define _MY_SUPER_TEMPLATE
  3.  
  4. [...] // Dein Template Code
  5.  
  6. #endif


Wenn's dann klappt gibt's die Erklärung :)

Aya


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: C++ Templates eine Methode
BeitragVerfasst: Di Mai 08, 2012 13:11 
Offline
DGL Member

Registriert: Mi Okt 16, 2002 15:06
Beiträge: 1012
Aya hat geschrieben:
Mach mal ein #ifdef drumrum:

Code:
  1. #ifndef _MY_SUPER_TEMPLATE
  2. #define _MY_SUPER_TEMPLATE
  3.  
  4. [...] // Dein Template Code
  5.  
  6. #endif


Wenn's dann klappt gibt's die Erklärung :)

Aya


Jede header datei bei mir hat nen #pragma once.
Das veranlasst den compiler dass er es nur einmal deklariert.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: C++ Templates eine Methode
BeitragVerfasst: Di Mai 08, 2012 16:22 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2623
Wohnort: Berlin
Programmiersprache: Go, C/C++
Pragma gehört nicht zum standard und macht auf einigen compilern probleme und ist in der regel auch nicht so gut wie ifdef. Hatte mal vor ne weile nen artikel gelesen, weswegen ich dann das pragma, was ich zusätzlich zu ifdef drin hatte, entfernte.

Du hast die spezialisierung in die cpp gelegt, dort liegt die falsch, da nun mit hilfe des generischen Load eine implementierung gemacht wird und mit der spezialisierten version, in der cpp er dann bei nutzung dieser zu einem konflikt führt, gibt es ja nun 2 mal.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: C++ Templates eine Methode
BeitragVerfasst: Mi Mai 09, 2012 12:55 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
ich schreibs hier mal drunter, da meine Edits für gewöhnlich übersehen werden: wir haben *code* tags, bitte nutzt sie: [code=cpp]foobar[ /code] (ohne leerzeichen vor dem / versteht sich ;))

grüße

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: C++ Templates eine Methode
BeitragVerfasst: Mi Mai 09, 2012 16:52 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2623
Wohnort: Berlin
Programmiersprache: Go, C/C++
Da es ne kniffelige Sache ist, wollte ich nochmal die Endgültige Lösung aufzeigen.
Hier ein bisschen Code aus mein Framework, welches template spezialisierung auf Methoden zeigt.
Wichtig ist, dass für jede spezialisierung eine definition und declaration existiert und beides in dem Header liegt.
Man sollte auch immer den Typen mit vollständigen Namespace für den template parameter angeben, da VSC++ z.B. Amok läuft, wenn man dies nicht Tut.
Im Folgendem Code z.B. ist NetService eigentlich von RadonFramework namespace umgeben und man müsste nicht bei den Typen RadonFramework::.... schreiben sondern kann diesen Namespace weg lassen aber wenn es ein Template parameter ist, dann nicht.
Code:
  1. class NetService
  2. {
  3.     public:
  4.         // This method retrieves a socket option.
  5.         template <typename T>
  6.         static Error GetSocketOption(const SocketHandler Handler,
  7.             const Net::SocketOptionLevel::Type OptionLevel,
  8.             const Net::SocketOptionName::Type OptionName,
  9.             T& OptionValue);
  10.  
  11.         // specialized case if T is RadonFramework::Memory::AutoPointerArray<RadonFramework::Core::Types::UInt8>
  12.         template <>
  13.         static Error GetSocketOption<RadonFramework::Memory::AutoPointerArray<RadonFramework::Core::Types::UInt8> >(
  14.             const SocketHandler Handler,
  15.             const Net::SocketOptionLevel::Type OptionLevel,
  16.             const Net::SocketOptionName::Type OptionName,
  17.             RadonFramework::Memory::AutoPointerArray<RadonFramework::Core::Types::UInt8>& OptionValue);
  18.     private:
  19.         /** This method is the internal version without any protection
  20.           * against wrong pointer arithmetic and type size.
  21.           **/
  22.         static Error GetSocketOption(const SocketHandler Handler,
  23.             const Net::SocketOptionLevel::Type OptionLevel,
  24.             const Net::SocketOptionName::Type OptionName,
  25.             Memory::AutoPointerArray<Core::Types::UInt8>& Value);
  26. };
  27.  
  28. template <typename T>
  29. RadonFramework::System::Network::NetService::Error
  30.     RadonFramework::System::Network::NetService::GetSocketOption(
  31.         const RadonFramework::System::Network::NetService::SocketHandler Handler,
  32.         const RadonFramework::Net::SocketOptionLevel::Type OptionLevel,
  33.         const RadonFramework::Net::SocketOptionName::Type OptionName,
  34.         T& OptionValue)
  35. {
  36.     RadonFramework::Memory::AutoPointerArray<RadonFramework::Core::Types::UInt8> arr(
  37.         new RadonFramework::Core::Types::UInt8[sizeof(T)],sizeof(T));
  38.     RadonFramework::System::Network::NetService::Error result=
  39.         GetSocketOption(Handler,OptionLevel,OptionName,arr);
  40.     if (result==RadonFramework::System::Network::NetService::Ok)
  41.     {
  42.         if (arr.Size()==sizeof(T))
  43.             OptionValue=*arr.Get();
  44.         else
  45.             result=RadonFramework::System::Network::NetService::InvalidArguments;
  46.     }
  47.     return result;
  48. }
  49.  
  50. template <>
  51. RadonFramework::System::Network::NetService::Error
  52.     RadonFramework::System::Network::NetService::GetSocketOption<RadonFramework::Memory::AutoPointerArray<RadonFramework::Core::Types::UInt8> >(
  53.     const RadonFramework::System::Network::NetService::SocketHandler Handler,
  54.     const RadonFramework::Net::SocketOptionLevel::Type OptionLevel,
  55.     const RadonFramework::Net::SocketOptionName::Type OptionName,
  56.     RadonFramework::Memory::AutoPointerArray<RadonFramework::Core::Types::UInt8>& OptionValue)
  57. {
  58.     return GetSocketOption(Handler,OptionLevel,OptionName,OptionValue);
  59. }
  60.  
  61. // cpp file
  62. NetService::Error NetService::GetSocketOption(const NetService::SocketHandler Handler,
  63.     const SocketOptionLevel::Type OptionLevel,
  64.     const SocketOptionName::Type OptionName,
  65.     AutoPointerArray<UInt8>& Value)
  66. {
  67.     return GetSocketOptionImplementation(Handler,OptionLevel,OptionName,Value);// system dependent code
  68. }

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: C++ Templates eine Methode
BeitragVerfasst: Do Mai 10, 2012 16:46 
Offline
DGL Member

Registriert: Mi Okt 16, 2002 15:06
Beiträge: 1012
Ha, es funktioniert danke :)


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 5 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.009s | 15 Queries | GZIP : On ]