2015-06-24 14 views
5

Ho una classe come:inizializzazione uniforme con parentesi graffa è scambiato come lista di inizializzazione

#include <memory> 

class Object { 
    std::shared_ptr<void> object_ptr; 
public: 
    Object() {} 

    template<typename T> 
    Object(T&& object) 
     : object_ptr {new T {std::move(object)} } {} 

    virtual ~Object() {}; 
}; 

Il mio file cpp principale è:

#include <iostream> 
#include "Object.hpp" 

class Foo {}; 


int main() { 
    Object o {Foo{}}; 
} 

Mi dà errore:

test/test.cpp:13:20: required from here 
include/Object.hpp:24:49: error: could not convert ‘{std::move<Foo&>((* & object))}’ from ‘<brace-enclosed initializer list>’ to ‘Foo’ 
     : object_ptr {new T {std::move(object)} } {} 
               ^
include/Object.hpp:24:49: error: no matching function for call to ‘std::shared_ptr<void>::shared_ptr(<brace-enclosed initializer list>)’ 
include/Object.hpp:24:49: note: candidates are: 
In file included from /usr/include/c++/4.8/memory:82:0, 
       from include/Object.hpp:7, 
       from test/test.cpp:2: 
/usr/include/c++/4.8/bits/shared_ptr.h:314:2: note: template<class _Alloc, class ... _Args> std::shared_ptr<_Tp>::shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) 
    shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a, 
^
/usr/include/c++/4.8/bits/shared_ptr.h:314:2: note: template argument deduction/substitution failed: 
/usr/include/c++/4.8/bits/shared_ptr.h:265:17: note: constexpr std::shared_ptr<_Tp>::shared_ptr(std::nullptr_t) [with _Tp = void; std::nullptr_t = std::nullptr_t] 
     constexpr shared_ptr(nullptr_t __p) noexcept 
       ^
/usr/include/c++/4.8/bits/shared_ptr.h:265:17: note: no known conversion for argument 1 from ‘<type error>’ to ‘std::nullptr_t’ 
/usr/include/c++/4.8/bits/shared_ptr.h:257:2: note: template<class _Tp1, class _Del> std::shared_ptr<_Tp>::shared_ptr(std::unique_ptr<_Up, _Ep>&&) 
    shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) 
^
/usr/include/c++/4.8/bits/shared_ptr.h:257:2: note: template argument deduction/substitution failed: 
/usr/include/c++/4.8/bits/shared_ptr.h:253:2: note: template<class _Tp1> std::shared_ptr<_Tp>::shared_ptr(std::auto_ptr<_Up>&&) 
    shared_ptr(std::auto_ptr<_Tp1>&& __r); 
^
/usr/include/c++/4.8/bits/shared_ptr.h:253:2: note: template argument deduction/substitution failed: 
/usr/include/c++/4.8/bits/shared_ptr.h:248:11: note: template<class _Tp1> std::shared_ptr<_Tp>::shared_ptr(const std::weak_ptr<_Tp1>&) 
    explicit shared_ptr(const weak_ptr<_Tp1>& __r) 
     ^
/usr/include/c++/4.8/bits/shared_ptr.h:248:11: note: template argument deduction/substitution failed: 
/usr/include/c++/4.8/bits/shared_ptr.h:236:2: note: template<class _Tp1, class> std::shared_ptr<_Tp>::shared_ptr(std::shared_ptr<_Tp1>&&) 
    shared_ptr(shared_ptr<_Tp1>&& __r) noexcept 
^
/usr/include/c++/4.8/bits/shared_ptr.h:236:2: note: template argument deduction/substitution failed: 
/usr/include/c++/4.8/bits/shared_ptr.h:226:7: note: std::shared_ptr<_Tp>::shared_ptr(std::shared_ptr<_Tp>&&) [with _Tp = void] 
     shared_ptr(shared_ptr&& __r) noexcept 
    ^
/usr/include/c++/4.8/bits/shared_ptr.h:226:7: note: no known conversion for argument 1 from ‘<type error>’ to ‘std::shared_ptr<void>&&’ 
/usr/include/c++/4.8/bits/shared_ptr.h:218:2: note: template<class _Tp1, class> std::shared_ptr<_Tp>::shared_ptr(const std::shared_ptr<_Tp1>&) 
    shared_ptr(const shared_ptr<_Tp1>& __r) noexcept 
^
/usr/include/c++/4.8/bits/shared_ptr.h:218:2: note: template argument deduction/substitution failed: 
/usr/include/c++/4.8/bits/shared_ptr.h:206:2: note: template<class _Tp1> std::shared_ptr<_Tp>::shared_ptr(const std::shared_ptr<_Tp1>&, _Tp*) 
    shared_ptr(const shared_ptr<_Tp1>& __r, _Tp* __p) noexcept 
^
/usr/include/c++/4.8/bits/shared_ptr.h:206:2: note: template argument deduction/substitution failed: 
/usr/include/c++/4.8/bits/shared_ptr.h:184:2: note: template<class _Deleter, class _Alloc> std::shared_ptr<_Tp>::shared_ptr(std::nullptr_t, _Deleter, _Alloc) 
    shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a) 
^
/usr/include/c++/4.8/bits/shared_ptr.h:184:2: note: template argument deduction/substitution failed: 
/usr/include/c++/4.8/bits/shared_ptr.h:165:2: note: template<class _Tp1, class _Deleter, class _Alloc> std::shared_ptr<_Tp>::shared_ptr(_Tp1*, _Deleter, _Alloc) 
    shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a) 
^
/usr/include/c++/4.8/bits/shared_ptr.h:165:2: note: template argument deduction/substitution failed: 
/usr/include/c++/4.8/bits/shared_ptr.h:146:2: note: template<class _Deleter> std::shared_ptr<_Tp>::shared_ptr(std::nullptr_t, _Deleter) 
    shared_ptr(nullptr_t __p, _Deleter __d) 
^
/usr/include/c++/4.8/bits/shared_ptr.h:146:2: note: template argument deduction/substitution failed: 
/usr/include/c++/4.8/bits/shared_ptr.h:129:2: note: template<class _Tp1, class _Deleter> std::shared_ptr<_Tp>::shared_ptr(_Tp1*, _Deleter) 
    shared_ptr(_Tp1* __p, _Deleter __d) 
^
/usr/include/c++/4.8/bits/shared_ptr.h:129:2: note: template argument deduction/substitution failed: 
/usr/include/c++/4.8/bits/shared_ptr.h:112:11: note: template<class _Tp1> std::shared_ptr<_Tp>::shared_ptr(_Tp1*) 
    explicit shared_ptr(_Tp1* __p) 
     ^
/usr/include/c++/4.8/bits/shared_ptr.h:112:11: note: template argument deduction/substitution failed: 
/usr/include/c++/4.8/bits/shared_ptr.h:103:7: note: std::shared_ptr<_Tp>::shared_ptr(const std::shared_ptr<_Tp>&) [with _Tp = void] 
     shared_ptr(const shared_ptr&) noexcept = default; 
    ^
/usr/include/c++/4.8/bits/shared_ptr.h:103:7: note: no known conversion for argument 1 from ‘<type error>’ to ‘const std::shared_ptr<void>&’ 
/usr/include/c++/4.8/bits/shared_ptr.h:100:17: note: constexpr std::shared_ptr<_Tp>::shared_ptr() [with _Tp = void] 
     constexpr shared_ptr() noexcept 
       ^
/usr/include/c++/4.8/bits/shared_ptr.h:100:17: note: candidate expects 0 arguments, 1 provided 
make: *** [test.o] Error 1 

Tuttavia se cambio new T {std::move(object)} in new T (std::move(object)). Funziona:

class Object { 
    std::shared_ptr<void> object_ptr; 
public: 
    Object() {} 

    template<typename T> 
    Object(T&& object) 
     : object_ptr {new T (std::move(object)) } {} 

    virtual ~Object() {}; 
}; 

Perché l'inizializzazione uniforme di parentesi graffa non funziona qui? Perché è considerato un elenco di inizializzazione in questo caso? Foo non ha nemmeno un costruttore che prende l'elenco di inizializzatori?

+1

Questo è un possibile duplicato di [Usa std :: move in C++ 11 move constructor con una sintassi di inizializzazione uniforme] (http://stackoverflow.com/questions/15864269/use-stdmove-in-c11-move- costruttore-con-uniforme-inizializzazione-sintassi). –

+0

Perché sei 'nuovo' e non usi' std :: make_shared'? –

+0

Vedere [LWG 1467] (http://open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1467). – 0x499602D2

risposta

4

Questo era un problema noto e un difetto nello standard (vedere CWG #1467). La proposta è stata applicata alla più recente documento di lavoro (§8.5.4 [dcl.init.list]/3):

List-initialization of an object or reference of type T is defined as follows:

  • If T is a class type and the initializer list has a single element of type cv U , where U is T or a class derived from T , the object is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization).

Nota che le versioni tronco di Clang e GCC accettano questo codice.

+0

Potrebbe essere risolto in C++ 11 o nuovo standard ? – texasbruce

+1

@texasbruce Non sei sicuro di cosa intendi. Clang ha già implementato questa modifica nella sua ultima versione. Il paragrafo precedente è stato aggiunto allo standard C++ 14. – 0x499602D2

+0

"* Se' T' è un tipo di classe * "... sembra strano. Sono abbastanza sicuro che funzionerebbe anche con il tipo di struct, perché questa formulazione? : O –

Problemi correlati