Sign in to follow this  
kerilynne

Creating a shared pointer out of typename T_

Recommended Posts

Here is the code, I'll bold the function I'm working with: I was just changing the resource manager to seperate the add resource method from the request resource method and creating a new method entirely, Manage_Resource.
#ifndef RESOURCE_MANAGER_H
#define RESOURCE_MANAGER_H

#include <vector>
#include <map>
#include <string>
#include <boost\shared_ptr.hpp>
#include <boost\weak_ptr.hpp>
#include <iostream>

template< typename T_ >
class Resource_Manager
{  

public:

	typedef T_ value_type; // std library convention 

	typedef boost::shared_ptr<T_> Resource_Ptr;
	typedef boost::weak_ptr<T_> Resource_Observer;
	typedef std::map< std::string, Resource_Ptr > Resource_Map;
	Resource_Manager<T_>() {};
	~Resource_Manager<T_>() {};
[b]
	bool Manage_Resource(const std::string & name, T_)
	{
		Resource_Map::iterator it = mResources.find(name);
		if (it == mResources.end())
		{
			Resource_Ptr Raw_Resource(T_);
			mResources.insert(std::make_pair(name,  Raw_Resource));
			return true;
		}
		else
		{
			return false;
		}
	}
[/b]
	Resource_Observer Request_Resource(const std::string & name)
	{
		Resource_Map::iterator  it = mResources.find(name);

		if (it == mResources.end())
		{
			std::cout << "This resource does not exist!";
			/*
			Resource_Ptr Raw_Resource(new T_);
			mResources.insert(std::make_pair(name, Raw_Resource));
			Resource_Observer Resource(Raw_Resource);
			return Resource;
			*/
		}
		else
		{
			return Resource_Observer(it->second);
		}
	}

	void Remove_Resource(const std::string & name)
	{
		Resource_Map::iterator it = mResources.find(name);

		if (it != mResources.end())
		{
			mResources.erase(it);
		}
	}

private:
	Resource_Map  mResources;
};

#endif

That code compiled fine but now I'm trying to use it like so, and getting compiler errors:


	void initialize_player(std::string player_id)
	{
		Player * new_player = new Player(player_id);
		m_rPlayers.Manage_Resource( player_id, new_player );
	}
I'm not quite sure what I'm doing wrong, but here is the first few errors it generates:
error C2664: 'Resource_Manager<T_>::Manage_Resource' : cannot convert parameter 2 from 'Player *' to 'Player'
        with
        [
            T_=Player
        ]
        No constructor could take the source type, or constructor overload resolution was ambiguous
I've tried switching parameters and changing pointers to references to values and I can't get any entries to work, any idea what I'm doing wrong?

Share this post


Link to post
Share on other sites
You have the line bool Manage_Resource(const std::string & name, T_), which defines a function taking two parameters. The second parameter is of type T_ (presumably Player in this instantiation). It has no name and is not used by the function. Then you have the lines Player * new_player = new Player(player_id); m_rPlayers.Manage_Resource( player_id, new_player );, the second of which passes a pointer to a Player (instead of a Player) to the function. This is exactly what the error message is telling you. Learning to interpret these error messages (they're not Greek) will be a useful way to spend your time.

Share this post


Link to post
Share on other sites
I changed the parameter like this before but it led to another error that made me backtrack... But I realize that extra error was just me not completing the function by creating the shared pointer out of type instead of T_.

I've changed the parameter for manage_resource to take a T_ * type in the second parameter.


bool Manage_Resource(const std::string & name, T_ * type)
{
Resource_Map::iterator it = mResources.find(name);
if (it == mResources.end())
{
Resource_Ptr Raw_Resource(type);
mResources.insert(std::make_pair(name, Raw_Resource));
return true;
}
else
{
return false;
}
}




This works :)

I just wasn't paying close enough attention to details I suppose, in the line Resource_Ptr Raw_Resource(type) there used to be a T_ there, which was causing extra errors when I actually passed a pointer, which I'm doing now.

But now that I see it it is fixed!

Share this post


Link to post
Share on other sites
Quote:
Original post by kerilynne
The reason I'm posting is because the error is misleading.


Except that it wasn't - C++ is just evil.
'Resource_Manager<T_>::Manage_Resource' : cannot convert parameter 2 from 'Player *' to 'Player'
Obvious... You're passing Player *, and second parameter of function accepts Player.

The following however:
No constructor could take the source type, or constructor overload resolution was ambiguous
is why C++ is tricky.

Consider this:
void foo( const std::string & s );

foo("Hello World");


What would happen if your Player class were defined as follows:
struct Player
{
Player() {};
Player( Player * other ) {} // special copy constructor
};


The code you posted would compile, and lots of hilarity would ensue.

What would happen would be the following:
// template instantiation for Player
bool Manage_Resource(const std::string & name, Player p)
{
};

...

void initialize_player(std::string player_id)
{
Player * new_player = new Player(player_id);
Player __temp( new_player ); // generated by compiler
m_rPlayers.Manage_Resource( player_id, __temp ); // passed by value
}


This is why it's a good idea to mark non-default constructors as explicit. The reason your compiler failed was because after trying to do the above, the following happened:
void initialize_player(std::string player_id)
{
Player * new_player = new Player(player_id);
Player __temp( new_player ); // E2664: Player has no constructor taking Player *
m_rPlayers.Manage_Resource( player_id, __temp );
}


The compiler in this case reported the correct error, but the problem comes from a direction you didn't expect or were aware of.

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