Hogyan kell kezelni az auto_ptr megszüntetésének tervmódosítását a C ++ 11-ben?

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

  • A auto_ptr valamelyik hatóköre kiterjed (azaz std::auto_ptr), szükségük van-e rá, vagy az intelligens mutató más névtérből beszerezhető-e?
  • Félretéve érdemes a Foo::Initialize fájlt hajtani a Foo::Foo fájlba.
  • @ MSalters – igen, ez mindig is egyike volt azoknak, amelyek miatt enyhén kényelmetlenül éreztem magam. A könyvtárat az 1990-es években terveztük, és úgy gondolom, hogy a kialakítás hasonló volt az MFC-hez. C ++ szintű konstrukció, majd egy " magasabb szintű " objektum konstrukció. Úgy gondolom, hogy a funkciót kompromisszumként használták, így az osztályok nem ' t 6 vagy 12 különböző konstruktorral rendelkezik. (Ezen a ponton átéltem, amit tettem, és biztosítottam, hogy a POD típusok tagváltozói észszerű alapértékekre inicializálódjanak a C ++ konstruktorokban).

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, mint my_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

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.

  • @jww. Gondolom, hogy a fordító, a könyvtár és a céleszköz egy adott keverékét figyelembe véve szükség lehet még néhány kézi állványra. Egyébként fontolja meg az OS X rendszeren a clang és a libc ++ használatát. Őszintén szólva úgy vélem, hogy a libc ++ az új " natív " C ++ könyvtár az OS X számára – ezt alapértelmezés szerint beállítanám. Nem áll módomban alátámasztani ezeket az állításokat azon kívül, hogy a clang / Apple kapcsolat története és az OS X GCC eszközei elavultnak tűnnek (könyvtár) vagy éppen eltávolításra kerültek ).
  • " Egyébként az OS X-en vegye fontolóra a clang és a libc ++ lépését … " – igen, valahogy egyetértek veled. Szeretnénk azonban hagyni, hogy a felhasználók döntsenek, és ne kényszerítsék rájuk. (Implicit módon választanak, ha megadják (vagy hiányzik) CXX=...).
  • Itt ' az eset ami annyi problémát okoz nekem az OS X 10.7 és 10.8 operációs rendszereken: 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:

    1. Ú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.

    2. 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.

    3. 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.

    Vélemény, hozzászólás?

    Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük