web-dev-qa-db-fra.com

équivalent boost unique_ptr?

Existe-t-il une classe équivalente pour std :: unique_ptr de C++ 1x dans les bibliothèques boost? Le comportement que je recherche est d'avoir une fonction d'usine sans danger, comme ça ...

std::unique_ptr<Base> create_base()
{
    return std::unique_ptr<Base>(new Derived);
}

void some_other_function()
{
    std::unique_ptr<Base> b = create_base();

    // Do some stuff with b that may or may not throw an exception...

    // Now b is destructed automagically.
}

EDIT: En ce moment, j'utilise ce hack, qui semble être le meilleur que je puisse obtenir à ce stade ...

Base* create_base()
{
    return new Derived;
}

void some_other_function()
{
    boost::scoped_ptr<Base> b = create_base();

    // Do some stuff with b that may or may not throw an exception...

    // Now b is deleted automagically.
}
54
Clark Gaebel

Il n'est pas possible de créer quelque chose comme unique_ptr sans C++ 0x (où il fait partie de la bibliothèque standard, et donc Boost n'a pas besoin de le fournir).

Plus précisément sans références rvalue, qui sont une fonctionnalité de C++ 0x, une implémentation robuste de unique_ptr est impossible, avec ou sans Boost.

En C++ 03, il existe quelques alternatives possibles, bien que chacune ait ses défauts.

  • boost::shared_ptr est probablement le remplacement le plus simple en termes de capacités. Vous pouvez l'utiliser en toute sécurité partout où vous utiliseriez autrement un unique_ptr et ça marcherait. Ce ne serait tout simplement pas aussi efficace, en raison du comptage de référence ajouté. Mais si vous cherchez un simple remplacement sans rendez-vous capable de tout gérer unique_ptr peut faire, c'est probablement votre meilleur pari. (Bien sûr, un shared_ptr peut aussi faire beaucoup plus, mais il peut aussi simplement être utilisé en remplacement de unique_ptr.)
  • boost::scoped_ptr est similaire à unique_ptr mais ne permet pas le transfert de propriété. Il fonctionne très bien tant que le pointeur intelligent est destiné à conserver la propriété exclusive tout au long de sa durée de vie.
  • std::auto_ptr fonctionne de manière très similaire à unique_ptr, mais présente quelques limitations, principalement parce qu'il ne peut pas être stocké dans des conteneurs de bibliothèque standard. Si vous recherchez simplement un pointeur qui permet le transfert de propriété, mais qui n'est pas destiné à être stocké dans des conteneurs ou copié, c'est probablement un bon pari.
68
jalf

À partir de Boost 1.57 il y a une implémentation officielle de unique_ptr Dans la bibliothèque Boost.Move .

De la documentation :

(...) un remplacement direct de std :: unique_ptr, utilisable également à partir des compilateurs C++ 03.

Le code est disponible dans le fichier d'en-tête <boost/move/unique_ptr.hpp> Et réside dans l'espace de noms boost::movelib. De plus, la bibliothèque Boost.Move fournit make_unique() fonction d'usine dans <boost/move/make_unique.hpp>, Également dans boost::movelib Espace de noms.

Par conséquent, l'exemple de la question pourrait être mis en œuvre de cette façon:

#include <boost/move/unique_ptr.hpp>

using boost::movelib::unique_ptr;

unique_ptr<Base> create_base()
{
    return unique_ptr<Base>(new Derived);
}

Voir n exemple en direct sur Wandbox . Notez que le code compile correctement avec gcc 4.6.4 en mode C++ 98 (!).

Ce qui est intéressant dans boost::movelib::unique_ptr Lorsqu'il est appliqué à votre cas avec des classes de base/dérivées, l'implémentation fournit une vérification au moment de la compilation pour la déclaration d'un destructeur virtuel dans la classe de base. S'il vous arrive de l'omettre le code ne compilera pas (cliquez sur le bouton "Exécuter (...)" pour voir le message d'erreur du compilateur).

Un problème mineur est que les inclusions proviennent du répertoire boost/move Mais le code vit dans l'espace de noms boost::movelib (Différence subtile mais peut être ennuyeux).

Voir aussi n fil sur la liste de diffusion boost pour plus de détails.

Merci à Ion Gaztañaga pour ce morceau de code absolument unique et utile.

33
Adam Romanek

Vous voudrez peut-être essayer la "preuve de concept" de Howard Hinnant unique_ptr<> implémentation pour C++ 03 (avertissement - je n'ai pas):

Un de ses exemples renvoie un unique_ptr<int>:

unique_ptr<int> factory(int i)
{
    return unique_ptr<int>(new int(i));
}
10
Michael Burr

Que diriez-vous unique_ptr à partir de la bibliothèque interprocess ?

5
fbrereto

J'ai utilisé le Howard_innant unique_ptr . Si vous n'êtes pas vraiment bon pour lire les erreurs de métaprogrammation folles de votre compilateur, vous voudrez peut-être éviter. Il agit cependant comme un unique_ptr dans 90% des cas.

Sinon, je suggérerais de passer des paramètres comme boost::scoped_ptr& et permutez en interne pour voler la propriété. Pour obtenir des valeurs de retour de style unique_ptr, utilisez un auto_ptr. Capturez le auto_ptr renvoie la valeur dans un shared_ptr ou scoped_ptr pour éviter d'utiliser le auto_ptr directement.

4
deft_code