Jump to content
  • Advertisement
Sign in to follow this  
Samurai Jack

Templates and non-public methods

This topic is 4523 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Greetings! I have a template class like this: myResource<T> { private: static vector<T*> m_ResorurceList; protected: virtual void Load(char* pszFileName); public: T* GetResource(char* pszFileName) { if pszFileName not in m_ResourceList then Load(pszFileName); } The problem is, that GetResource will complain when the class gets specialized, like this: class myTexture: public myResource<myTexture> { protected: void Load(char* pszFileName) { UploadTexture(); extend m_ResourceList with this; } ... The prloblem is, that myTexture->GetResource will now fail because of protected method Load. The only solution that I have right now goes like that: class myTexture : public myResource<myTexture> { firend class myResource<myTexture> ... Now it will work just fine. When I just copy this in the upper template like this: myResource<T> { firend class myResource<T>; The compiler will not complain but it will complain against Download! Urgh! Further more, i have implemented it so far, that my seeking functions became static, like this: myTexture* pHead = myTexture::Get("black_male.dds"); It works with the friend "work arround" but I would not like to have it posted in any derived resource. Thank you in advance and a Happy new year!

Share this post


Link to post
Share on other sites
Advertisement
Your class design seems a little confused. Why is myResource<T>::GetResource() not static?

Also, what compilation errors are you getting?

Share this post


Link to post
Share on other sites
Greetings!

The get method is static as I wrote. The error is: Can not access to protected members. This happens only with derivates, not with the design template.

it is like this:

static T* Get(char* pszFileName)
{
if pszFileName not in resource list then
{
T* pResource = new T();
t->Load(pszFileName); <- Here comes the error: can not access protected members
}

Share this post


Link to post
Share on other sites

template <typename T> class ngResource
{
private:
static std::list<T*> m_ResourcePool;

protected:
char m_szName[256];
DWORD m_dwFileSize;
DWORD m_nRefCount;

virtual bool Download(LPCSTR pszFileName)
{
ngCore::LogWrite("! Interface ngResource<T>::Download has not yet been implemented!\n");
ngCore::LogWrite("! File: %s\n", pszFileName);

MessageBox(NULL,
"Interface ngResource<T>::Download has not yet been implemented!",
"ngResource::Error",
MB_OK | MB_ICONERROR);

return false;
}

public:

//Constructor
ngResource(void)
{
T* pRes = (T*)this;
m_ResourcePool.push_back(pRes);
ZeroMemory(m_szName, sizeof(m_szName));
m_dwFileSize = 0L;
m_nRefCount = 0L;
}

//Destructor
virtual ~ngResource(void)
{
T* pRes = (T*)this;
m_ResourcePool.remove(pRes);
if (m_ResourcePool.empty()) m_ResourcePool.clear();
}

//Reference counting
inline DWORD AddRef(void) { return ++m_nRefCount; }
inline DWORD GetRefCount(void) { return m_nRefCount; }
inline void Release(void) { if (--m_nRefCount < 1) delete this; }
inline void UnRef(void) { if (m_nRefCount > 0) m_nRefCount--; }

//Basic properties
inline LPCSTR GetName(void) { return m_szName; }
inline DWORD GetFileSize(void) { return m_dwFileSize; }
static size_t GetResourceCount(void) { return m_ResourcePool.size(); }

//Master proxy function
static T* FindResource(LPCSTR pszFileName)
{
if (m_ResourcePool.empty() == true) return NULL;
if (pszFileName == NULL) return NULL;

std::list<T*>::iterator i;

for (i = m_ResourcePool.begin(); i != m_ResourcePool.end(); ++i)
{
T* pSrc = (T*)(*i);
if (!strcmp(pszFileName, pSrc->GetName()))
return pSrc;
}

return NULL;
}

static T* Load(LPCSTR pszFileName)
{
//Try to find the resource in the buffer
T* pRes = T::FindResource(pszFileName);

if (pRes != NULL)
{
//Instance allready present
pRes->AddRef();
return pRes;
}
else
{
//Instance not yet in database
DWORD dwFileSize = 0U;

FILE* fp = fopen(pszFileName, "rb");
if (fp == NULL)
{
ngCore::LogWrite("! ngResource::Error -> File '%s' not found.\n", pszFileName);
MessageBox(NULL, "File not found!", "ngResource::Error", MB_OK | MB_ICONERROR);
return NULL;
}
else
{
fseek(fp, 0L, SEEK_END);
dwFileSize = ftell(fp);
fclose(fp);
if (dwFileSize < 1U)
{
ngCore::LogWrite("! ngResource::Error -> File size too short (%d bytes).\n", dwFileSize);
MessageBox(NULL, "File too short!", "ngResource::Error", MB_OK | MB_ICONERROR);
return NULL;
}
}

T* pNew = new T;
pNew->m_dwFileSize = dwFileSize;
strcpy(pNew->m_szName, pszFileName);
if (pNew->Download(pszFileName) == true)
{
ngCore::LogWrite("* ngResource::Download: '%s' ok.\n", pszFileName);
ngCore::LogWrite("* ngResource::Resource Pool Size = %d\n", m_ResourcePool.size());
pNew->AddRef();
return pNew;
}
else
{
SAFE_RELEASE(pRes);
ngCore::LogWrite("! ngResource::Error -> Could not Load resource file (%s)\n", pszFileName);
MessageBox(NULL,
"Could not load resource file!",
"ngResource::Error",
MB_OK | MB_ICONERROR);
return NULL;
}
}
}
};

template <typename T> std::list<T*> ngResource<T>::m_ResourcePool;

Share this post


Link to post
Share on other sites
Load(filename) is just a proxy seek function.

Load looks in the table if resource is allready present. if it is not then it calls Download which is protected.

for example:

myTexture::Load("test.dds")

it will look up the cache and then call Download which is the source of all trouble.

I would not like that an user says:

myTexture* pTexture;
pTexture->Download("test.dds");

rather he shoud:

myTexture* pTexture = myTexture::Load("test.dds");

Share this post


Link to post
Share on other sites
But you said that "myTexture->GetResource will now fail because of protected method Load", and that the error occurs on the line on which Load is called.

Share this post


Link to post
Share on other sites
It appears that the friend declaration is necessary given your situation. You've set up the code so that they are to be derived from using CRTP, i.e. "class Texture : public ngResource<Texture>". The function ngResource<Texture>::Load() is not allowed to call Texture::Load() because ngResource<Texture> is not derived from Texture; therefore, ngResource<Texture>::Load() must be a friend of texture in order for ngResource<Texture>::Load() to call Texture::Download().


I have a few questions about your code:

* Why do you have protected member functions? It looks like you're going to end up with static dispatch. You won't need any sort of virtual dispatch unless you plan on doing something along the lines of "class PngTexture: public ngResource<Texture>".

* Why are you using std::list here? You're going to end up with a number of O(n) functions that you'd really rather want to be O(log n).

* What's the point of UnRef?

Share this post


Link to post
Share on other sites
Greetings!

thank you everyone! >Troll: The unref function is just like release except it does not destroy the object when the counter gets bellow one.

I will have to use the friend function for every derivate!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!