2011-12-16 17 views
13

Kod:Czy `unique_ptr <T const []>` akceptuje argument konstruktora `T *`?

#include <memory> 
using namespace std; 

struct T {}; 

T* foo() { return new T; } 
T const* bar() { return foo(); } 

int main() 
{ 
    unique_ptr< T const >  p1(bar());  // OK 
    unique_ptr< T const [] > a1(bar());  // OK 

    unique_ptr< T const >  p2(foo());  // OK 
    unique_ptr< T const [] > a2(foo());  // ? this is line #15 
} 

Przykładowe błędy z Visual C++ 10.0 i MinGW g ++ 4.4.1:

 
[d:\dev\test] 
> cl foo.cpp 
foo.cpp 
foo.cpp(15) : error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>' 
     with 
     [ 
      _Ty=const T [] 
     ] 
     C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\memory(2509) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr' 
     with 
     [ 
      _Ty=const T [] 
     ] 

[d:\dev\test] 
> g++ foo.cpp -std=c++0x 
c:\program files (x86)\codeblocks\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/unique_ptr.h: In function 'int main()': 
c:\program files (x86)\codeblocks\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/unique_ptr.h:379: error: deleted function 'std::unique_ptr<_Tp [], _Tp_Deleter>::unique_ptr(_Up*, typename std::enable_if<std::is_convertible::value, void>::type*) [with _Up = T, _Tp = const T, _Tp_Deleter = std::default_delete<const T []>]' 
foo.cpp:15: error: used here 

[d:\dev\test] 
> _ 

Wydaje mi się, że wersja tablica powinna przyjąć takie samo niejawny const dodaną jako non -araska wersja.

Różnica polega na tym, że wersja tablicowa nie powinna akceptować wskaźnika do klasy pochodnej, a to jest mechanizm, który najwyraźniej kopie wyżej.

Czy kod jest prawidłowy?

Jeśli kod jest nieważny pod względem formalnym, czy standardowe sformułowanie odzwierciedla zamiar (tj. Czy DR jest właściwy)?

Jeśli nie na pierwszym i tak na drugim, czy cel jest wadliwy (tj. Ponownie, czy DR jest właściwy)?

Odpowiedz

9

Może być odpowiednie zgłoszenie błędu. §20.7.1.3.1 mówi

explicit unique_ptr(pointer p) noexcept; 
unique_ptr(pointer p, see below d) noexcept; 
unique_ptr(pointer p, see below d) noexcept; 

These konstruktorów zachowują się tak samo jak w pierwotnym szablonie tym wyjątkiem, że nie akceptują typy wskaźnika, które są wymienialne na wskaźnik. [Uwaga: Jedną z technik implementacji jest tworzenie prywatnych szablonowych przeciążeń tych elementów. - nota końcowa]

Pomysł wyraźnie polega na zapobieganiu konwersji pochodnych na podstawie, które nie działają z tablicami. Jest to jednak niespecyficzne i zabronione jest również przekształcanie kwalifikacji cv. Być może powinien on zostać zmieniony, aby zabronić konwersji wskaźników (§4.10), nie wszystkie konwersje wskaźników.

+1

"Typy wskaźnikowe, które można zamienić na wskaźnik" - i czy naprawdę dziurkacz, czy ten język jest niepoprawny? "wskaźnik" jest typem wskaźnika, który można przekształcić w wskaźnik (na przykład przy opisywaniu pojęć, jeśli jakaś funkcja zwraca typ "zamienny na T", nie oznacza to, że nie może to być sam T). Ale nie sądzę, że intencją było pominięcie "wskaźnika" oraz wskaźników do typów pochodnych ;-) –

+0

Umieściłem difort riport na csC++, ale może to trochę potrwać, aby pojawić się ... więc, tylko dla informacji, Cytowałem też, co myślę, jest intencją/racjonalnością w §20.7.1.3/1 2 myślnik, "Wskaźniki do typów pochodnych od T są odrzucane przez konstruktorów, a przez reset" :-) –

+2

To wygląda dla mnie jak usterka. Zajrzyj na: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#submit_issue. Zaimplementowałem rozwiązanie w libC++ (http://libcxx.llvm.org/). Trudniej było uzyskać rację, niż się domyślałem! –

Powiązane problemy