Testaamme kirjastoa C ++ 11: ssä (ts. -std=c++11
). Kirjasto käyttää auto_ptr
ja tätä mallia:
Foo* GetFoo() { autoptr<Foo> ptr(new Foo); // Initialize Foo ptr->Initialize(...); // Now configure remaining attributes ptr->SomeSetting(...); return ptr.release(); }
C ++ 11 vanhentunut auto_ptr
, joten haluamme siirtyä pois siitä.
Koodi kuitenkin tukee sekä C ++ 03: ta että C ++ 11: tä, joten se ei ole yksinkertainen kuin yanking auto_ptr
. On myös syytä mainita, että kirjastolla ei ole ulkoisia riippuvuuksia. Se käyttää C ++ 03: ta eikä käytä Autotools-, Cmake-, Boost-, …
Kuinka meidän tulisi käsitellä suunnittelumuutoksia siirtyäksesi pois auto_ptr
mallille C ++ 11 säilyttäen yhteensopivuus C ++ 03: n kanssa?
Kommentit
Vastaa
Useimmiten std::unique_ptr
tehtiin pudotettavaksi (mutta turvallisempi) std::auto_ptr
-korvaus, joten koodimuutoksia, joita vaaditaan, on oltava hyvin vähän muuten kuin mahdollista (kun kysyt) ohjaamalla koodi käyttämään joko unique_ptr
tai auto_ptr
.
On olemassa muutama tapa tehdä tämä (ja jokaisella on omat listansa kompromissit) alla. Annetun koodinäytteen perusteella suosittelen kahta ensimmäistä vaihtoehtoa .
Vaihtoehto 1
#if __cplusplus >= 201103L template <typename T> using auto_ptr = std::unique_ptr<T>; #else using std::auto_ptr; #endif
Kompromissit;
- Lisää
auto_ptr
-nimi globaaliin nimiavaruuteen ; voit lieventää tätä määrittelemällä, että se on oma " yksityinen " nimiavaruus - Kun olet siirtänyt C ++ 17: een (Uskon, että
auto_ptr
poistetaan kokonaan). Voit etsiä ja korvata helpommin.
Vaihtoehto 2
template <typename T> struct my_ptr { #if __cplusplus >= 201103L typedef std::unique_ptr<T> ptr; #else typedef std::auto_ptr<T> ptr; #endif };
Kompromissit;
- Todennäköisesti hankalampi työskennellä, kaikki nykyiset
auto_ptr
on muutettava koodissa jotainmy_ptr<T>::ptr
- Paremman turvallisuuden vuoksi nimiä ei lisätä globaaliin nimiavaruuteen
Vaihtoehto 3
Hieman kiistanalainen, mutta jos olet valmis sietämään varoitukset siitä, että std
-luokka on perusta
#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
Kompromissit;
- Älä yritä käyttää perittyä luokkaa, jossa virtuaalisen tukikohdan (erityisesti kirjoitetun ei-virtuaalisen tuhoajan) odotetaan olevan. Ei, että tämän pitäisi olla asia – mutta ole tietoinen siitä
- Koodimuutokset jälleen
- Mahdolliset nimiavaruudet eivät täsmää – kaikki riippuu siitä, miten osoitinluokka aloitetaan
Vaihtoehto 4
Kääri osoittimet uuteen luokkaan ja koota tarvittavat toiminnot jäsenelle
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(); } };
Kompromissit;
- A vähän äärimmäistä, kun kaikki mitä todella haluat, on " vaihtaa " toteutukset ulos
kommentit
- Erittäin hyvä vastaus. Tutkin itse asiassa sitä vähän, ja osui ainakin kolme testistä, jotka yritin. (Sinulta puuttuu OS X- ja Clang-spesifisiä juttuja. OS X on karhu, koska se käyttää silti ajoittain TR1-nimitilaa C ++ 03: lle, ja sinun on sisällytettävä asiat tällä menetelmällä: Ei tyyppiä nimeltä ' unique_ptr ' nimitilassa ' std ' käännettäessä LLVM / Clangissa ).
- @jww. <
m OS X: ssä (XCode 6.4 ja Apple LLVM -versio 6.1.0 (clang-602.0.53) (perustuu LLVM 3.6.0svn: iin)) ja minulla ei ole ongelmia C: n kanssa ++ 03/11 sekoitus, joka ei ole muu kuin tr1
-nimitila (en käytä libc ++ eikä libstdc ++).Tiedän, että tr1 ei ollut normatiivista, mutta en voi ' löytää mistään -luonnoksesta (täällä) , että tiedostojen piti olla lainkaan <tr1/...>
, infact mainitsee vain olevan otsikossa <memory>
jne. vain tr1
nimiavaruus.
CXX=...
). c++ -v -std=c++11 -x c++ - < /dev/null
. grep'd
sisällytän tyhjennetyt hakemistot, ja ne eivät sisältävät unique_ptr
. vastaus
Vaihtoehto 5: Suora alias.
#if __cplusplus >= 201103L template<typename T> using MyPtr = std::unique_ptr<T>; #else #define MyPtr std::auto_ptr #endif
Kompromissit:
-
Uudemmille kieliversioille, AKA C ++ 11 ja uudemmat, alias-tyyppisi yhdistää oikean älyosoittimen. Kääntäjä merkitsee kaikki käyttäjäkoodit, jotka tosiasiallisesti riippuvat tavalliselle standardille :: auto_ptr määritetyistä sovellusliittymistä, mikä takaa lopullisen korjauksen.
-
Vanhassa versiossa c ++ 03-tilassa tyypin alias on makro. Tämä on karkea, mutta tuloksena syntaksin
MyPtr<T>
tulee olemaan identtinen C ++ 11 -tapahtuman kanssa koko koodissa. / p> -
Sinun on löydettävä ja muutettava kaikki auto_ptr-muuttujat
MyPtr
-asetuksiksi tämän määrittämiseksi.
Kommentit
- ' on hyvin epäselvää, mihin tämä viittaa (ja kuten sanottu se ei ole lainkaan ' ta kysymys).
- @autophage uskon sen vastauksen … joten luultavasti ei kysymys.
auto_ptr
-luokitelluista alueista (ts.std::auto_ptr
), onko niiden oltava vai voidaanko älykäs osoitin saada jostakin muusta nimiavaruudesta?Foo::Initialize
osaksiFoo::Foo
.