Nous testons une bibliothèque sous C ++ 11 (cest-à-dire -std=c++11
). La bibliothèque utilise auto_ptr
et ce modèle:
Foo* GetFoo() { autoptr<Foo> ptr(new Foo); // Initialize Foo ptr->Initialize(...); // Now configure remaining attributes ptr->SomeSetting(...); return ptr.release(); }
C ++ 11 obsolète auto_ptr
, nous voulons donc nous en éloigner.
Cependant, le code prend en charge à la fois C ++ 03 et C ++ 11, donc ce nest pas aussi simple que de tirer auto_ptr
. Il est également intéressant de mentionner que la bibliothèque na pas de dépendances externes. Elle utilise C ++ 03; et nutilise pas Autotools, Cmake, Boost, …
Comment devons-nous gérer les changements de conception pour séloigner de auto_ptr
pour C ++ 11 tout en conservant la compatibilité avec C ++ 03?
Commentaires
Réponse
À bien des égards, le std::unique_ptr
a été conçu pour être ajouté (mais plus sûr) remplacement de std::auto_ptr
, il ne devrait donc y avoir que très peu de changements de code (le cas échéant) autres que (comme vous le demandez) en dirigeant le code pour quil utilise soit unique_ptr
soit auto_ptr
.
Il existe plusieurs façons de procéder ceci (et chacun vient avec sa propre liste de compromis) ci-dessous. Compte tenu de lexemple de code fourni, je préférerais lune des deux premières options .
Option 1
#if __cplusplus >= 201103L template <typename T> using auto_ptr = std::unique_ptr<T>; #else using std::auto_ptr; #endif
Compromis;
- Vous introduisez le nom
auto_ptr
dans lespace de noms global ; vous pouvez atténuer ce problème en définissant quil sagit de votre propre espace de noms " private " - Une fois migré vers C ++ 17 (Je pense que
auto_ptr
sera complètement supprimé) vous pouvez rechercher et remplacer plus facilement
Option 2
template <typename T> struct my_ptr { #if __cplusplus >= 201103L typedef std::unique_ptr<T> ptr; #else typedef std::auto_ptr<T> ptr; #endif };
Compromis;
- Probablement plus compliqué à travailler, tous les
auto_ptr
actuels doivent être modifiés dans le code en quelque chose commemy_ptr<T>::ptr
- Plus de sécurité, les noms ne sont pas introduits dans lespace de noms global
Option 3
Un peu controversé, mais si vous êtes prêt à accepter la mise en garde davoir une classe std
comme base
#if __cplusplus >= 201103L template <typename T> using my_ptr = std::unique_ptr<T>; #else template <typename T> class my_ptr : public std::auto_ptr<T> { // implement the constructors for easier use // in particular explicit my_ptr( X* p = 0 ) : std::auto_ptr(p) {} }; #endif
Compromis;
- Nessayez pas dutiliser la classe héritée là où une base virtuelle (en particulier avec le destructeur non virtuel) serait attendue. Non pas que cela devrait être un problème dans laffaire – mais sachez-le
- Encore une fois, le code change
- Différences potentielles despace de noms – tout dépend de la façon dont la classe de pointeur est utilisée pour commencer par
Option 4
Enveloppez les pointeurs dans une nouvelle classe et agrégez les fonctions requises au membre
template <typename T> class my_ptr { // could even use auto_ptr name? #if __cplusplus >= 201103L std::unique_ptr<T> ptr_; #else std::auto_ptr<T> ptr_; #endif // implement functions required... T* release() { return ptr_.release(); } };
Compromis;
- A petit extrême quand tout ce que vous voulez vraiment est de " swap " les implémentations en dehors
Commentaires
- Très bonne réponse. En fait, je lai fait un peu de recherche et vous avez réussi au moins trois des tests que jai essayés. (Ce qui vous manque, ce sont les éléments spécifiques à OS X et à Clang. OS X est un ours car il utilise encore parfois lespace de noms TR1 pour C ++ 03, et vous devez inclure des éléments en utilisant cette méthode: Aucun type nommé ' unique_ptr ' dans lespace de noms ' std ' lors de la compilation sous LLVM / Clang ).
- @jww. Je ' m sous OS X (XCode 6.4 et Apple LLVM version 6.1.0 (clang-602.0.53) (basé sur LLVM 3.6.0svn)) et nai aucun problème avec le C ++ 03/11 mix autre que lespace de noms
tr1
nétant plus là (jutilise libc ++ et non libstdc ++).Je sais que tr1 nétait pas normatif, mais je ne peux ' trouver nulle part dans le brouillon (ici) que le les fichiers devaient être<tr1/...>
du tout, en fait, il mentionne simplement être dans len-tête<memory>
etc. fichier juste dans letr1
espace de noms. - @jww. Je suppose que, étant donné un mélange particulier de compilateur, de bibliothèque et de périphérique cible, vous devrez peut-être faire quelques supports supplémentaires. Sinon, sous OS X, envisagez de passer à clang et libc ++. Franchement, je considère que la libc ++ est la nouvelle bibliothèque C ++ " native " pour OS X – je le ferais par défaut. Je nai aucun moyen de soutenir ces affirmations autres que lhistoire de la relation clang / Apple et que les outils GCC sur OS X semblent obsolètes (bibliothèque) ou simplement supprimés (pour autant que je sache, GCC est un mince bout à cliqueter de toute façon ).
- " Sinon, sous OS X, envisagez de passer à clang et libc ++ … " – ouais, je suis plutôt daccord avec vous. Cependant, nous aimerions laisser les utilisateurs faire ce choix et ne pas le leur imposer. (Ils font implicitement le choix lorsquils spécifient (ou manquent) de
CXX=...
). - Ici ' cest le cas cela me cause tellement de problèmes sur OS X 10.7 et 10.8:
c++ -v -std=c++11 -x c++ - < /dev/null
. Jegrep'd
les répertoires dinclusion qui ont été vidés, et ils nincluent pasunique_ptr
.
Réponse
Option 5: Alias direct.
#if __cplusplus >= 201103L template<typename T> using MyPtr = std::unique_ptr<T>; #else #define MyPtr std::auto_ptr #endif
Compromis:
-
Pour les versions linguistiques plus récentes, AKA C ++ 11 et versions ultérieures, votre type dalias correspond au pointeur intelligent approprié. Tout code utilisateur qui dépend en fait dAPI spécifiques à std :: auto_ptr sera signalé par le compilateur, ce qui est la garantie ultime quil « sera vraiment corrigé.
-
In Legacy Mode c ++ 03, lalias de type est une macro. Cest grossier, mais la syntaxe résultante
MyPtr<T>
sera identique au cas C ++ 11 dans le reste du code. -
Vous devez trouver et changer toutes vos variables auto_ptr en
MyPtr
pour configurer cela.
Commentaires
- Il ' nest pas clair de quoi il sagit (et, comme formulé, ce nest pas ' une question).
- @autophage Je crois que cest une réponse … donc probablement pas une question.
auto_ptr
ont-ils une portée (cest-à-direstd::auto_ptr
), doivent-ils lêtre ou le pointeur intelligent peut-il être obtenu à partir dun autre espace de noms?Foo::Initialize
enFoo::Foo
.