Kuinka käsitellä suunnittelumuutoksia auto_ptr-poistolle C ++ 11: ssä?

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

  • Onko jokin auto_ptr -luokitelluista alueista (ts. std::auto_ptr), onko niiden oltava vai voidaanko älykäs osoitin saada jostakin muusta nimiavaruudesta?
  • Voit sivuuttaa sivun Foo::Initialize osaksi Foo::Foo.
  • @ MSalters – joo, se on aina ollut yksi niistä asioista, joista olen tuntenut lievää epämukavuutta. Kirjasto on suunniteltu 1990-luvulla, ja mielestäni mielestäni muotoilu on samanlainen kuin MFC. tason C ++ rakentaminen ja sitten " korkeamman tason " objektirakenne. Luulen, että ominaisuutta käytettiin kompromissina, joten luokat eivät ' t on 6 tai 12 erilaista konstruktoria. (Tässä vaiheessa tekemäni on käynyt läpi ja varmistanut, että POD-tyyppien jäsenmuuttujat alustetaan järkeviin oletusarvoihin C ++ -konstruktoreissa.)

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 jotain my_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

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.

  • @jww. Luulen, että kun otetaan huomioon tietty kääntäjän, kirjaston ja kohdelaitteen yhdistelmä – sinun on ehkä tehtävä vielä muutama käsijalusta. Harkitse muuten OS X: ssä siirtymistä clangiin ja libc ++: iin. Suoraan sanottuna katson libc ++: n uudeksi " alkuperäiseksi " C ++ -kirjastoksi OS X: lle – oletusasetuksena on se. Minulla ei ole mitään tapaa tukea näitä väitteitä muulla tavoin, että clang / Apple-suhteen historia ja että OS X: n GCC-työkalut näyttävät olevan vanhentuneita (kirjasto) tai juuri poistettuja (sikäli kuin tiedän, GCC on ohut tynkä, joka klastaa joka tapauksessa ).
  • " Harkitse muuten OS X: ssä siirtymistä clangiin ja libc ++ … " – joo, olen tavallaan samaa mieltä kanssasi. Haluamme kuitenkin antaa käyttäjien tehdä tämän valinnan eikä pakottaa sitä heille. (He tekevät valinnan implisiittisesti, kun ne määrittelevät (tai puuttuvat) CXX=...).
  • Tässä ' s tapaus se aiheuttaa minulle niin paljon ongelmia OS X 10.7: ssä ja 10.8: ssa: 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:

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

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

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

    Vastaa

    Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *