2015-06-01 13 views
9

Ten przykład kompiluje się i działa dobrze z gcc 4.8.3:unique_ptr konstruktor z niestandardowym Deleter zostanie usunięty

#include <memory> 
#include <functional> 
#include <iostream> 

int main() { 
    auto str = new const char[6]{'h', 'e', 'l', 'l', 'o', '\0'}; 
    std::unique_ptr<const char[], std::function<void(const char *)>> u_ptr(str, [](const char *s){ delete[] s; }); 
    std::cout << u_ptr.get() << std::endl; 
} 

Ale gdy próbuję go z Visual Studio Professional 2013 to nie kompiluje (narzeka na usuniętej funkcji). Czy to nie jest jeszcze możliwe w Visual Studio 2013? Czy mój kod przykładowy jest nieprawidłowy, a gcc ignoruje mój błąd?

Błąd jest:

main.cpp (8): error C2280: 'std :: unique_ptr> :: unique_ptr> (_ PTR2, _Dx2)': próbuje odwołać usuniętą funkcję z [ _Ptr2 = const char *, _Dx2 = główny :: ] C: \ Program Files (x86) \ Microsoft Visual Studio 12.0 \ VC \ INCLUDE \ memory (16 16): patrz deklaracja 'std :: unique_ptr>: : unique_ptr '

+0

Działa z dzwonkiem. –

+3

Powinny być FAQ na "dlaczego używasz' std :: function' jako 'unique_ptr' deleter strasznego pomysłu?" –

+0

[OT]: ponieważ niczego nie przechwytujesz, możesz pominąć niepotrzebne '=' w '[=]'. – Jarod42

Odpowiedz

6

To wydaje się być defekt w bibliotece standardowej Visual C++ 2013. Nie mogę odtworzyć problemu na 2015

Klasa unique_ptr ma tego konstruktora do podejmowania wskaźnik i Deleter:

unique_ptr(pointer _Ptr, 
    typename _If<is_reference<_Dx>::value, _Dx, 
     const typename remove_reference<_Dx>::type&>::type _Dt) _NOEXCEPT 
    : _Mybase(_Ptr, _Dt) 
    { // construct with pointer and (maybe const) deleter& 
    } 

jednak specjalizacja unique_ptr<T[]> posiada również catch-all konstruktora:

template<class _Ptr2, 
    class _Dx2> 
    unique_ptr(_Ptr2, _Dx2) = delete; 

Ta wersja jest preferowana od poprzedniej.

Jednakże, ponieważ niewyspecjalizowana unique_ptr nie ma go wcale, zmieniając u_ptr do const char zamiast const char[] rozwiązuje problem.

Korzystanie wersję tablicy z Deleter jak robisz jest również konieczne:

  1. Jeśli chcesz zadzwonić delete[] na wskaźnik, jest już specjalizacja dla tablic. Nie potrzebujesz niestandardowego deletera.

  2. Jeśli chcesz zrobić coś innego, powinieneś użyć wersji nie wyspecjalizowanej.

+0

as Wspomniałem w moim komentarzu do pytania 'std :: unique_ptr ' jest już dostarczone. Nie ma potrzeby stosowania tutaj niestandardowego separatora. – Mgetz

+1

@Mgetz OP pyta, czy jego kod jest poprawny pod względem składni (i dlaczego kompilatory się nie zgadzają). Istnienie już odpowiedniego deletera jest nieistotne, ponieważ dostarczył [MCVE] (http://stackoverflow.com/help/mcve) i może potrzebować, w rzeczywistym rzeczywistym problemie, użyć niestandardowego deletera. –

Powiązane problemy