2015-04-27 10 views
7

Czasami temu widziałem kodu:Inteligentny wskaźnik Deleter i „za” słowo kluczowe z nazwą „wskaźnik”

void* Create() 
{ 
    int* t{new int{10}}; 
    return t; 
} 

class Deleter 
{ 
    //uncomment in order to compile 
    //using pointer = void*; 
public: 
    void operator()(void* t) 
    { 
     delete t; 
    } 
}; 

unique_ptr<int, Deleter> ptr{Create()}; 

to nie kompiluje. Z VS2013 mówi:

error: C2440: 'initializing' : cannot convert from 'initializer-list' to 'std::unique_ptr' No constructor could take the source type, or constructor overload resolution was ambiguous

Ale gdybym Odkomentuj linia using pointer = void*; to działa! Również jeśli zmienię nazwę aliasu na coś innego niż pointer, pojawia się ten sam błąd. Tak więc wydaje się, że kluczowe znaczenie ma posiadanie dyrektywy using o dokładnej nazwie pointer. Ale dlaczego? Nie mogłem znaleźć żadnego wyjaśnienia.

Odpowiedz

6

Twój unique_ptr zadeklarowany z T=int. Jednak zamiast tego należy przyjmować argument zamiast T*, ale.

Ten pointer typ zdefiniowany jako

std::remove_reference<Deleter>::type::pointer if that type exists, otherwise T* 

A jeśli nie zapewniają Deleter::pointer kończy się jak int*, no i oczywiście nie mogą być inicjowane z void* (od Create).

1

[C++11: 20.7.1.2/3] If the type remove_reference<D>::type::pointer exists, then unique_ptr<T, D>::pointer shall be a synonym for remove_reference<D>::type::pointer . Otherwise unique_ptr<T, D>::pointer shall be a synonym for T* . The type unique_ptr<T, D>::pointer shall satisfy the requirements of NullablePointer (17.6.3.3).

Jest tu wymagana, ponieważ nie masz operator()(int*) - jesteś „hacking” wokół, że aby umożliwić operator()(void*) być stosowany zamiast przez czyniąc Deleter udawać, że to Deleter dla void*.

Niezależnie od tego, czy Twój deleter jako całość pozostaje ściśle obowiązujący, nawet gdy się kompiluje, nie chciałbym powiedzieć.

Powiązane problemy