jac*_*bsa 22 c++ type-traits language-lawyer libc++ c++17
在我的 clang 和 libc++ 版本(near HEAD
)中,这static_assert
通过了:
static_assert(std::is_copy_constructible_v<std::vector<std::unique_ptr<int>>>)
Run Code Online (Sandbox Code Playgroud)
当然,如果您实际上尝试复制构造唯一指针的向量,它将无法编译:
../include/c++/v1/__memory/allocator.h:151:28: error: call to implicitly-deleted copy constructor of 'std::unique_ptr<int>'
::new ((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
[...]
note: in instantiation of member function 'std::vector<std::unique_ptr<int>>::vector' requested here
const std::vector<std::unique_ptr<int>> bar(foo);
^
../include/c++/v1/__memory/unique_ptr.h:215:3: note: copy constructor is implicitly deleted because 'unique_ptr<int>' has a user-declared move constructor
unique_ptr(unique_ptr&& __u) _NOEXCEPT
Run Code Online (Sandbox Code Playgroud)
我认为这种情况是因为实现在不可复制构造std::vector<T>
时不使用 SFINAE 来禁用复制构造函数。T
但为什么不呢?标准中是否有规定必须以这种方式工作?这是不幸的,因为这意味着我自己的围绕复制构造性的 SFINAE 并没有在向量方面做正确的事情。
use*_*522 28
std::vector
和其他容器(除了std::array
)被指定有一个复制构造函数。这并未指定为以元素类型是否可复制为条件。如果元素类型不可复制,则仅禁止复制构造函数定义的实例化。
std::is_copy_constructible_v
因此容器上的结果将永远是true
。无法测试定义的实例化是否具有类型特征的格式良好。
如果元素类型不可复制,则可以指定不声明复制构造函数或将其排除在重载解析之外。然而,这会带来一个权衡,这篇博文中详细解释了这一点:https: //quuxplusone.github.io/blog/2020/02/05/vector-is-copyable- except-when-its-不是/。
简而言之,如果我们希望能够使用不完整类型的容器,例如递归地像
struct X {
std::vector<X> x;
};
Run Code Online (Sandbox Code Playgroud)
那么我们X
在实例化容器类时就无法判断是否是可复制的。因此,复制构造函数的声明不能依赖于此属性。
自 C++17 起,标准要求std::vector
、std::list
和std::forward_list
,但不要求其他容器,才能像这样处理不完整类型。
归档时间: |
|
查看次数: |
1385 次 |
最近记录: |