2012-12-09 2 views
1
#include <SFML/Graphics.hpp> 
#include <memory> 
#include <map> 

int main(int argc, char **argv) 
{ 
std::map <const std::string, std::shared_ptr<sf::Texture> > resources; 
sf::Texture tempResource; 
tempResource.loadFromFile("1.PNG"); 

resources.insert(std::pair<const std::string, std::shared_ptr<sf::Texture>>("1", std::dynamic_pointer_cast<sf::Texture>(new sf::Texture(tempResource)))); 

return 0; 
} 

(que les nouvelles utilisations d'appel constructeur de copie)casting pointeur normal à std :: shared_ptr ne semble pas fonctionner

Sans coulée (juste appeler la nouvelle fonction d'insertion à l'intérieur), il ne fonctionne pas. J'ai donc utilisé shared_ptr casting pour le faire, mais cela ne fonctionne pas. L'erreur: erreur: aucune fonction de mise en correspondance pour l'appel à « dynamic_pointer_cast (sf :: Texture *) »

Quel est le problème ici, comment puis-je le faire fonctionner? Je suis nouveau sur shared_ptrs et je ne peux pas le résoudre moi-même.

Merci

Répondre

0

Qu'est-ce que vous voulez faire est la création d'un shared_ptr de mémoire non géré auparavant. dynamic_pointer_cast n'est pas l'outil pour le travail. Au lieu de cela cela devrait fonctionner:

resources.insert(std::pair<const std::string, std::shared_ptr<sf::Texture>>("1", std::shared_ptr<sf::Texture>(new sf::Texture(tempResource))); 
//or: 
resources.insert(std::make_pair("1", std::shared_ptr<sf::Texture>(new sf::Texture(tempResource))); 

Cependant la construction d'un shared_ptr de la mémoire nouvellement allouée est quelque peu wasterful. puisque cela fait deux allocations (une pour la mémoire et une pour les données internes du shared_ptr). Si vous utilisez std::make_shared(tempResource) ces deux allocations peuvent être combinées en une pour une efficacité plus élevée.

C++ 11 permettrait également resources.emplace("1", std::make_shared(tempResource) pour la construction inplace de la paire, mais la dernière fois que j'ai vérifié le support du compilateur pour cela manquait quelque peu.

Comme une note de côté: si vous n'avez pas besoin tempResource plus, vous voudrez peut-être envisager de déplacer (au lieu de le copier dans la structure de données en utilisant std::move(tempResource) au lieu de tempResource pour constructiong l'objet nouvellement allouée En fonction de la mise en œuvre. sf::texture Si l'objet n'est pas réellement déplaçable (donc la construction de mouvement est fondamentalement identique à une copie), vous pouvez construire directement le Texture en shared_ptr et en appelant la charge sur celui:

auto tempResource = std::make_shared<sf::Texture>(); 
tempResource->loadFromFile("1.PNG"); 
resources.emplace("1",std::move(tempResource));//or insert if emplace isn't availible 
+0

Merci! Grande réponse – user1873947

+0

@ user1873947: Si cela résout votre problème, vous pouvez envisager d'accepter soit Kerrek ou ma réponse pour montrer que le problème est résolu. Bien sûr, upvoting une réponse est aussi une bonne façon de montrer de la gratitude;) – Grizzly

+0

Je ne peux pas voter à cause de ma faible rep ... Les deux réponses sont bonnes mais je vais choisir la vôtre parce que vous avez rep inférieur. – user1873947

0

Vous devriez dire:

std::map<std::string, std::shared_ptr<sf::Texture>> resources; 
     // ^^^ "const" is redundant 

// ... 

resources.insert(std::make_pair("1", std::make_shared<sf::Texture>(tempResource))); 

Si votre plate-forme prend en charge, vous pouvez même dire:

resources.emplace("1", std::make_shared<sf::Texture>(tempResource)); 

Ou:

resources.emplace("1", new sf::Texture(tempResource)); 

Mais ce n'est pas aussi bon que make_shared, ce qui est plus efficace, et il viole la règle de bon goût de ne jamais utiliser new. De toute façon, le point de emplace est qu'il autorise les constructeurs explicites, contrairement à insert.


Même encore mieux est cela, ne pas utiliser temporaire du tout:

resources.emplace("1", std::make_shared<sf::Texture>()).second->loadFromFile("1.PNG"); 
+0

Merci cela semble la meilleure façon, mais ... g ++ soutiendra emplace s ince 4.8 ... meh ... Eh bien, je vais le faire pour le moment et faire le commentaire pour le mettre à jour quand 4.8 sera libéré. – user1873947

+0

@ user1873947: Bien sûr, mais scrap que temporaire dans tous les cas et aller avec la solution finale (vous pouvez faire quelque chose de similaire avec 'insert'). –

+0

sûr, mais j'en ai besoin dans la fonction resManager :: add, donc j'ai besoin de faire un design pour qu'il ne crée pas 2 instances de la même chose. Cependant, cela devrait être plutôt facile. – user1873947