2011-12-16 6 views
13

Codice:Dovrebbe `unique_ptr <T const []>` accettare un argomento di costruzione `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 
} 

errori di esempio con Visual C++ 10.0 e 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] 
> _ 

Mi sembra che la versione array dovrebbe accettare lo stesso implicita const aggiunto come il non -array versione.

La differenza è che la versione dell'array non deve accettare il puntatore a una classe derivata, e questa è la macchina che apparentemente spunta in alto.

Il codice è valido?

Se il codice è formalmente non valido, il testo dello standard riflette l'intento (cioè, è un DR appropriato)?

Se no al primo e sì al secondo, l'intento è difettoso (cioè, di nuovo, è un DR appropriato)?

risposta

9

Un rapporto sui difetti può essere appropriato. §20.7.1.3.1 dice,

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

Questi costruttori si comportano come nel modello primario, tranne che non accettano tipi di puntatore che sono convertibili al puntatore. [Nota: una tecnica di implementazione consiste nel creare sovraccarichi temporizzati di questi membri. - end note]

L'idea è chiaramente quella di impedire conversioni derivate che non funzionano con gli array. Ma è una conversione non specifica e la qualifica di cv è proibita. Forse dovrebbe essere cambiato per proibire le conversioni del puntatore (§4.10), non tutte le conversioni di puntatori.

+1

"tipi di puntatore convertibili in puntatore" - e per fare davvero il pelo nell'uovo, comunque, questo linguaggio non è corretto? 'pointer' è un tipo di puntatore convertibile in puntatore (ad esempio quando si descrivono concetti, se alcune funzioni restituiscono un tipo" convertibile in T ", ciò non significa che non debba essere T stesso). Ma non penso che l'intenzione fosse quella di escludere il 'pointer' come un puntatore ai tipi derivati ​​;-) –

+0

ho postato difect riportare a csC++, ma potrebbe richiedere del tempo per apparire ... quindi, solo per informazioni, Ho anche citato quello che penso sia l'intento/razionale in §20.7.1.3/1 secondo trattino, "I puntatori ai tipi derivati ​​da T sono respinti dai costruttori, e da reset" :-) –

+2

Questo mi sembra un difetto. Si prega di seguire a: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#submit_issue. Ho implementato una soluzione in libC++ (http://libcxx.llvm.org/). Era più difficile avere ragione di quanto stavo indovinando! –