2015-06-24 14 views
5

Ich habe eine Klasse wie:Uniform Initialisierung mit geschweifte Klammer irrt als Initialisierungsliste

#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() {}; 
}; 

Meine Haupt CPP-Datei ist:

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

class Foo {}; 


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

Es gibt mir Fehler:

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 

Allerdings, wenn ich new T {std::move(object)} zu new T (std::move(object)) ändern. Es funktioniert:

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() {}; 
}; 

Warum geschweifte Klammer einheitliche Initialisierung funktioniert hier nicht? Warum wird in diesem Fall eine Initialisiererliste betrachtet? Foo hat nicht einmal einen Konstruktor, der Initialisiererliste nimmt?

+1

Dies ist eine mögliche Duplikat [Verwendung std :: in C++ Konstruktor 11 bewegen einheitlicher Syntax Initialisierung Verschieben] (http://stackoverflow.com/questions/15864269/use-stdmove-in-c11-move- Konstruktor mit Uniform-Initialisierungs-Syntax). –

+0

Warum nimmst du 'new' und nicht' std :: make_shared'? –

+0

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

Antwort

4

Dies war ein bekanntes Problem, und ein Defekt in der Norm (siehe CWG #1467). Der Vorschlag wurde auf das neueste Arbeitspapier aufgebracht (§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).

Beachten Sie, dass Stamm-Versionen von Clang und GCC diesen Code akzeptieren.

+0

Wäre es ++ 11 oder neuer Standard in c festgelegt werden ? – texasbruce

+1

@texasbruce Nicht sicher, was Sie meinen. Clang hat diese Änderung bereits in seiner neuesten Version implementiert. Der obige Absatz wurde dem C++ 14-Standard hinzugefügt. – 0x499602D2

+0

"* Wenn' T' ein Klassentyp ist * "... klingt das komisch. Ich bin mir ziemlich sicher, dass es auch mit struct type funktionieren würde, warum diese Formulierung? : O –

Verwandte Themen