Sign in to follow this  
TroneX

Template-Driven Resource Manager, Compiler Problem

Recommended Posts

Hi folks, I am trying to implement a template driven resource manager. I've got sample sources from Sam Lantinga and are about to change some things. Unfortunately these changes produce some warning I didn't get rid of yet, maybe you've got an idea: A little code-snippet
template<class T> class CResourceCache
{
    public:
        CResourceCache( void )
        {
            m_vCache.clear();
        }    
        
    protected:
        typedef struct Cache
        {
            string strName;
            T *data;
        };            

        vector<Cache> m_vCache;             
};    

As you can see, I am referencing the template class within the Cache struct which I am trying to create an stl vector of. My compiler now is concerned about that vector<Cache> statement and says that implicit typenames are deprecated: [Warning] implicit typename is deprecated, please see the documentation for details But whatever I did to that statement, I was not able to resolve this problem. Does anyone of you know the solution? Regards, T.

Share this post


Link to post
Share on other sites
Why are you typedefing your struct to an empty name? As it is I can compile your code under gcc, but it generates an error under Borland C++ because of the typedef. Removing the typedef enables me to compile it with no errors or warnings under both gcc and Borland C++.

Enigma

Share this post


Link to post
Share on other sites
You are right! Thanks! Removing the typedef solved part of the problem.
But now there's still another of the same type.

Here a part, I didn't post before:

The following snippet is taken out of the class as shown in the post above

(...)
protected:
struct Cache
{
string strName;
T *data;
};

vector<Cache> m_vCache;

T *Find( const string strName )
{
T *data;

for( vector<Cache>::iterator itrCache = m_vCache.begin(); itrCache != m_vCache.end(); ++itrCache )
{
(...)
}

}



On the vector<Cache>::iterator above, I am getting the same warning about deprecated implicit typenames...

Share this post


Link to post
Share on other sites
Why are you using vector for this? Shouldn't std::map (or hashmap) be much better option. It gets rid of 'Cache' structure and gives you O(logN) or O(1) search time.

Share this post


Link to post
Share on other sites
Hm. You got me.

For a moment, I thought: Because a map is slower than a vecotr due to all of these string comparisons...

Then, something popped into my mind: I am doing exactly the same, except that my code won't be as optimized for this as a map already is... plus: it's kind of bloated that way.

So you're right. I'll try using a map.
Thanks for the hint!

T.

But: Can you explain though, why I am getting the warning and how to fix this?

Share this post


Link to post
Share on other sites
choice 1: using a vector of pair of string & smart pointer to resource:


#include <boost\smart_ptr.hpp>
#include <utility>
#include <algorithm>
#include <string>
#include <vector>

template<class Resource>
struct resource_mgr {

typedef boost::shared_ptr<Resource> res_ptr;
typedef std::pair<std::string, res_ptr> res_pair;
typedef std::vector< res_pair > res_vec;
typedef typename res_vec::iterator res_itr;
typedef typename res_vec::const_iterator const_res_itr;

private:

res_vec resources;

struct res_find {

const std::string& res_name;

res_find(const std::string& _res_name): res_name(_res_name) {}

bool operator()(const res_pair& r) const {
return r.first == res_name;
}
};

resource_mgr(const resource_mgr<Resource>&);
resource_mgr<Resource>& operator=(const resource_mgr<Resource>&);

public:

static const res_ptr NULL_RESOURCE;

resource_mgr(typename res_vec::size_type num_to_cache = 0) {
resources.reserve(num_to_cache);
}

bool add_resource(const res_pair& f) {
if(std::find_if(resources.begin(), resources.end(), res_find(f.first)) != resources.end())
return false;
else {
resources.push_back(f);
return true;
}
}

const res_ptr& get_resource(const std::string& s) const {
const_res_itr itr = std::find_if(resources.begin(), resources.end(), res_find(s));
if(itr != resources.end()) {
return itr->second;
} else
return res_ptr();
}

res_ptr get_resource(const std::string& s) {
res_itr itr = std::find_if(resources.begin(), resources.end(), res_find(s));
if(itr != resources.end()) {
return itr->second;
} else
return res_ptr();
}

};

template < typename Resource >
const typename resource_mgr<Resource>::res_ptr resource_mgr<Resource>::NULL_RESOURCE;

#include <iostream>

struct foo {
int i;
foo(int j): i(j) {}
};

int main() {

typedef resource_mgr<foo> foo_res_mgr;

foo_res_mgr m(1);

m.add_resource(std::make_pair("foo", new foo(10)));

foo_res_mgr::res_ptr r;

if((r = m.get_resource("foo")) != foo_res_mgr::NULL_RESOURCE)
std::cout << r->i << '\n';
else
std::cout << "resource not found\n";

}






choice 2: using STL extension hash_map of strings to smart pointer to resource:

#include <boost\smart_ptr.hpp>
#include <string>
#include <hash_map>

template<class Resource>
struct resource_mgr {

typedef boost::shared_ptr<Resource> res_ptr;
typedef stdext::hash_map< std::string, res_ptr > res_vec;
typedef typename res_vec::iterator res_itr;
typedef typename res_vec::const_iterator const_res_itr;

private:

res_vec resources;

resource_mgr(const resource_mgr<Resource>&);
resource_mgr<Resource>& operator=(const resource_mgr<Resource>&);

public:

resource_mgr(): resources() {}

const res_ptr& operator[](const std::string& n) const {
return resources[n];
}

res_ptr& operator[](const std::string& n) {
return resources[n];
}
};

#include <iostream>

struct foo {
int i;
foo(int j): i(j) {}
};

int main() {

typedef resource_mgr<foo> foo_res_mgr;

foo_res_mgr m;

foo_res_mgr::res_ptr r(new foo(10));

m["foo"] = r;

std::cout << m["foo"]->i << '\n';

}






choice 3: using hash_map of strings to boost::any (this would be waste of time doing for a resource manager)


#include <boost\smart_ptr.hpp>
#include <boost\any.hpp>
#include <string>
#include <hash_map>

struct resource_mgr {

typedef stdext::hash_map< std::string, boost::any > res_vec;
typedef res_vec::iterator res_itr;
typedef res_vec::const_iterator const_res_itr;

private:

res_vec resources;

resource_mgr(const resource_mgr&);
resource_mgr& operator=(const resource_mgr&);

public:

resource_mgr(): resources() {}

/*const boost::any& operator[](const std::string& n) const {
return resources[n];
}*/


boost::any& operator[](const std::string& n) {
return resources[n];
}

};

#include <iostream>

struct foo {
int i;
foo(int j): i(j) {}
};

int main() {

resource_mgr m;

m["foo"] = foo(20);

std::cout << boost::any_cast<foo>(m["foo"]).i << '\n';

}




most definitely more choices available.

references: boost library

Share this post


Link to post
Share on other sites
Quote:
Original post by TroneX
Hm. You got me.

For a moment, I thought: Because a map is slower than a vecotr due to all of these string comparisons...

Then, something popped into my mind: I am doing exactly the same, except that my code won't be as optimized for this as a map already is... plus: it's kind of bloated that way.

So you're right. I'll try using a map.
Thanks for the hint!

T.

But: Can you explain though, why I am getting the warning and how to fix this?


You have to do:

typename vector<Cache>::iterator

because Cache is dependent on a template parameter. This means that even if you have vector's default definition included already (you can potentially even only have its declaration), the instantiated template may resolve to a specialization that has the iterator member defined to be anything, such as a datamember instead of a type, which makes it impossible to address without ambiguity in the template definition since the information can't normally be determined until the template is instantiated. It is impossible to know if vector<Cache>::iterator is a type or another form of member (datamember, memberfunction, etc) since that can't be known until you instantiate it. Using typename tells the compiler in advance that vector<Cache>::iterator should resolve to a type, otherwise it should result in error.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this