2013-03-20 3 views
3

Un membre est défini commeinitialisation shared_ptr

std::shared_ptr<std::array<std::string, 6> > exit_to; 

qui pointe vers des données supplémentaires partagés entre autres. Lorsque vous essayez d'initialiser le pointeur "exit_to". La manière correcte est

node_knot.exit_to = std::make_shared<std::array<std::string, 6> >(); 

Mais il est dans un autre dossier et je voudrais garder le type de pointeur cohérent, quelque chose comme ceci:

node_knot.exit_to = std::make_shared<decltype(*node_knot.exit_to)>(); 

Mais ne compilera pas:

/usr/include/c++/4.6/bits/shared_ptr_base.h:798:54: error: '__p' 
declared as a pointer to a reference of type 
'std::array<std::basic_string<char>, 6> &' 
     __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) 
                  ^/usr/include/c++/4.6/bits/shared_ptr.h:93:31: note: in instantiation 
of template class 
'std::__shared_ptr<std::array<std::basic_string<char>, 6> &, 1>' 
requested here 
    class shared_ptr : public __shared_ptr<_Tp> 
          ^../node_booker.h:757:20: note: in 
instantiation of template class 
'std::shared_ptr<std::array<std::basic_string<char>, 6> &>' requested 
here 
                 n.exit_to = std::make_shared<decltype(*n.exit_to)>(); 

Je suis sous Ubuntu 12.10, clang ++ 3.2, avec --std = C++ 11

Répondre

6

vous devez supprimer la référence du type que vous êtes passant à make_shared. Ce qui suit devrait fonctionner:

node_knot.exit_to = std::make_shared<std::remove_reference<decltype(*node_knot.exit_to)>::type>(); 
+0

Great! Je vais voir si remove_reference fait l'affaire! –

4

Le problème est que le type de *exit_to est une référence, et vous ne pouvez pas avoir un shared_ptr à une référence.

Vous pouvez supprimer la référence, mais au lieu de trouver le type retourné par operator* puis décaper la référence en dehors, il est probablement plus facile de demander au shared_ptr quel type il contient:

node_knot.exit_to = std::make_shared<decltype(node_knot.exit_to)::element_type>(); 

Le element_type imbriquée est le type stocké par le shared_ptr.

Une autre option serait d'ajouter un typedef à la classe et l'utiliser systématiquement partout où vous en avez besoin:

typedef std::array<std::string, 6> string_array; 
std::shared_ptr<string_array> exit_to; 

// ... 

node_knot.exit_to = std::make_shared<Node::string_array>(); 

C'est beaucoup plus lisible que l'utilisation decltype

+0

Je dirais que la construction 'decltype (node_knot.exit_to) :: element_type' va à l'encontre du but de decltype, puisque vous supposez (ou ajoutez la contrainte que) le type de node_knot.exit_to a un membre' element_type', n'est même pas vrai pour la plupart des types de STL. Votre deuxième solution sonne mieux cependant. Une observation cependant, y compris le nom du type dans le typedef lui-même en quelque sorte dévalue un typedef n'est-ce pas. Et l'avantage de typedefs est que vous pouvez changer le type de conteneur sous-jacent de votre string_array en n'importe quoi d'autre sans changer toutes les occurrences dans le code. –

+0

Cependant, mettre le '_array' dans' string_array' va à l'encontre de ce but, car une fois que le type sous-jacent change, le nom ne reflète plus le type. Voyez cette horrible chose appelée la notation hongroise, beurk: http://en.wikipedia.org/wiki/Hungarian_notation –

+0

@Zadirion, donc l'utilisation de 'make_shared' ne suppose pas déjà' shared_ptr'? En ce qui concerne le typedef, je suis d'accord en général, mais cela dépend des exigences sur le type. Si cela pouvait être n'importe quelle séquence, placer 'array' dans le nom serait trompeur, mais si c'est une exigence de conception qu'il ait des éléments contigus d'un type semblable à une chaîne, alors l'appeler' string_array' est correct, et fonctionne même si vous modifiez l'implémentation à 'vector ', ou juste à un tableau de longueur différente. Sans connaître plus de contexte, vous ne pouvez pas dire si le nom devrait être plus générique. –