Egy könyvtárat tesztelünk a C ++ 11 alatt (azaz -std=c++11
). A könyvtár a auto_ptr
és a következő mintát használja:
Foo* GetFoo() { autoptr<Foo> ptr(new Foo); // Initialize Foo ptr->Initialize(...); // Now configure remaining attributes ptr->SomeSetting(...); return ptr.release(); }
C ++ 11 elavult auto_ptr
, ezért el akarunk távolodni tőle.
A kód azonban támogatja a C ++ 03-at és a C ++ 11-et is, tehát nem olyan egyszerű, mint rángatózni auto_ptr
. Érdemes megemlíteni azt is, hogy a könyvtárnak nincsenek külső függőségei. Használja a C ++ 03-at; és nem használja az Autotools, a Cmake, a Boost …
Hogyan kell kezelni a tervezési változtatásokat az eltávolodáshoz auto_ptr
tól C ++ 11 esetén, megtartva a C ++ 03 kompatibilitását?
Megjegyzések
Válasz
A legtöbb szempontból a std::unique_ptr
-t cseppentették be (de biztonságosabb) a (z) std::auto_ptr
helyettesítése, ezért csak nagyon kevés (ha van) kódváltás szükséges, kivéve (ahogy kérdezi) a kód irányítása a unique_ptr
vagy a auto_ptr
használatára.
Van néhány módja ennek ezt (és mindegyikhez tartozik a saját lista kompromisszum) alább. Tekintettel a megadott kódmintára, az első két lehetőség bármelyikét előnyben részesíteném .
1. Opció
#if __cplusplus >= 201103L template <typename T> using auto_ptr = std::unique_ptr<T>; #else using std::auto_ptr; #endif
Kompromisszumok;
- Bevezeti a
auto_ptr
nevet a globális névtérbe ; enyhítheti ezt úgy, hogy meghatározza, hogy ez a saját " privát " névtér - Miután migrált a C ++ 17-be (Azt hiszem, hogy
auto_ptr
teljesen eltávolításra kerül) könnyebben kereshet és cserélhet
2. Lehetőség
template <typename T> struct my_ptr { #if __cplusplus >= 201103L typedef std::unique_ptr<T> ptr; #else typedef std::auto_ptr<T> ptr; #endif };
Kompromisszumok;
- Valószínűleg nehezebb dolgozni, az összes jelenlegi
auto_ptr
kódot át kell változtatni a kódban valami olyasmi, mintmy_ptr<T>::ptr
- Nagyobb biztonság érdekében a nevek nem kerülnek be a globális névtérbe
3. lehetőség
Kissé ellentmondásos, de ha készen állsz arra, hogy beletörődj a std
osztály alapjául szolgáló megfontolásokba
#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
Kompromisszumok;
- Ne próbálja meg használni az öröklött osztályt, ahol várható lenne egy virtuális bázis (különösen a nem virtuális rombolót írta). Nem mintha ez egy kérdés az ügyben – de legyen tisztában
- Ismételten megváltoznak a kódok
- A potenciális névtér nem egyezik – minden attól függ, hogy a mutatóosztályt hogyan kell kezdeni
4. opció
Csomagolja a mutatókat egy új osztályba, és összesítse a szükséges függvényeket a tag számára
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(); } };
Kompromisszumok;
- A kicsit szélsőséges, amikor csak annyit akarsz, hogy " kicseréld " a megvalósításokat
megjegyzések
- Nagyon jó válasz. Valójában utánanéztem egy kicsit, és legalább három tesztet eltaláltál. (Hiányzik az OS X és a Clang speciális cucca. Az OS X medve, mert néha még mindig a TR1 névteret használja a C ++ 03-hoz, és a dolgokat a következő módszerrel kell felvenned: Nincs ' unique_ptr ' nevű típus a névtérben ' std ' az LLVM / Clang alatt történő fordításkor).
- @jww. <
m OS X-en (XCode 6.4 és Apple LLVM 6.1.0 (clang-602.0.53) (LLVM 3.6.0svn alapján)), és nincs probléma a C A ++ 03/11 keverék, kivéve a tr1
névteret, amely már nincs (a libc ++ -ot használom, és nem a libstdc ++ -t).Tudom, hogy a tr1 nem normatív jellegű volt, de ' a vázlatban (itt) sehol nem találom, hogy a fájloknak egyáltalán <tr1/...>
-nek kellett lenniük, infact megemlíti, hogy csak a fejlécben vannak <memory>
stb., csak a tr1
névtér.
CXX=...
). c++ -v -std=c++11 -x c++ - < /dev/null
. grep'd
tartalmazza azokat a könyvtárakat, amelyek ki lettek dobva, és ezek nem tartalmazzák a unique_ptr
. Válasz
5. lehetőség: Közvetlen álnév.
#if __cplusplus >= 201103L template<typename T> using MyPtr = std::unique_ptr<T>; #else #define MyPtr std::auto_ptr #endif
Kompromisszumok:
-
Újabb nyelvi verziók esetén az AKA C ++ 11 és újabb verziók esetén az álnév típusa a megfelelő intelligens mutatóhoz társul. Minden olyan felhasználói kódot, amely valójában az std :: auto_ptr-re jellemző API-któl függ, a fordító megjelöli, ami a végső garancia arra, hogy valóban javítani fogják.
-
In Legacy c ++ 03 módban a típus álnév makró. Ez bruttó, de a kapott szintaxis
MyPtr<T>
a kód többi részében azonos lesz a C ++ 11 esettel. -
Ennek beállításához meg kell találnia és módosítania kell az összes auto_ptr változót
MyPtr
.
Megjegyzések
- ' nagyon nem világos, hogy mire utal ez (és ahogy megfogalmazva, egyáltalán nem ' ta kérdés).
- @autophage hiszem, hogy válasz … szóval valószínűleg nem kérdés.
auto_ptr
valamelyik hatóköre kiterjed (azazstd::auto_ptr
), szükségük van-e rá, vagy az intelligens mutató más névtérből beszerezhető-e?Foo::Initialize
fájlt hajtani aFoo::Foo
fájlba.