【问题标题】:Uniform Initialization with curly brace is mistaken as Initializer List带花括号的统一初始化被误认为是初始化列表
【发布时间】:2015-06-25 04:43:33
【问题描述】:

我有一门课:

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

我的主要 cpp 文件是:

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

class Foo {};


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

它给了我错误:

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

但是,如果我将 new T {std::move(object)} 更改为 new T (std::move(object))。它有效:

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

为什么大括号统一初始化在这里不起作用?为什么在这种情况下被认为是初始化列表? Foo 甚至没有构造函数来获取初始化列表?

【问题讨论】:

标签: c++ c++11


【解决方案1】:

这是一个已知问题,也是标准中的一个缺陷(请参阅CWG #1467)。该提案已应用于最新的工作文件(§8.5.4 [dcl.init.list]/3):

类型 T 的对象或引用的列表初始化定义如下:

  • 如果T 是一个类类型并且初始化列表有一个cv U 类型的元素,其中UT 或派生类 从T,对象从该元素初始化(通过复制列表初始化的复制初始化,或 通过直接初始化为直接列表初始化)。

请注意,ClangGCC 的中继版本接受此代码。

【讨论】:

  • 会在 c++11 或新标准中修复吗?
  • @texasbruce 不确定你的意思。 Clang 已经在其最新版本中实现了此更改。上述段落被添加到 C++14 标准中。
  • "如果 T 是类类型"...这听起来很奇怪。我很确定它也适用于 struct 类型,为什么要这样写? :O
  • @PaperBirdMaster - 根据标准,结构体也是类类型。
猜你喜欢
  • 2020-05-14
  • 2018-03-06
  • 1970-01-01
  • 1970-01-01
  • 2021-07-09
  • 2018-12-12
  • 1970-01-01
  • 2016-12-11
  • 1970-01-01
相关资源
最近更新 更多