都是 CopyConstructible 类型 MoveConstructible 类型
Are all CopyConstructible types MoveConstructible types?
根据工作草案N3337(与已发布的ISOC++11标准最相似的草案)和 cppreference.com,答案是肯定的。
N3337:
表 21 — 可复制可构造要求(除 MoveConstructible) [copyconstructible] [...]
cppreference.com:
类型 T 满足 CopyConstructible 如果
- 类型 T 满足 MoveConstructible,并且 [...]
但根据编译 main.cpp 与 gcc(Ubuntu 4.8.4-2ubuntu1~14.04)4.8.4 并使用 Ubuntu 14.04.3 LTS 中引用的语句运行 a.out 的结果,答案是否定的。
主.cpp:
#include <iostream>
#include <type_traits>
struct As
{
As()=default;
As(As&&)=delete;
As(const As&)=default;
As& operator=(As&&)=delete;
As& operator=(const As&)=delete;
~As()=default;
};
int main()
{
std::cout<<std::is_move_constructible<As>::value<<std::endl;
std::cout<<std::is_copy_constructible<As>::value<<std::endl;
return 0;
}
从终端编译和运行:
$ g++ -std=c++11 main.cpp
$ ./a.out
结果(输出):
0
1
我是否误解了什么,或者 N3337 和 cppreference.com 错了,或者 gcc 是否包含错误?
std::is_copy_constructible<T>
被定义为完全std::is_constructible<T, const T&>
即它只测试从常量左值构造是可能的,它不测试CopyConstructible概念的所有属性。
因此,您的测试不会显示您认为它显示的内容。您的类型不是 CopyConstructible 类型,因为它不符合其他一些要求。
至于最初的问题,是的。因为所有 CopyConstructible 类型都必须满足 MoveConstructible 的要求,所以它们都是 MoveConstructible 类型。MoveConstructible 不需要移动任何东西,只需要从右值构造是可能的,并且所有 CopyConstructible 类型都可以从右值构造(即使它们可能执行深层复制而不是移动)。
您可以创建可以从左值复制但不能从右值复制的反常类型,或者可以从常量左值复制但不能从非常量左值和其他可憎的东西复制。此类类型不是 CopyConstructible,并且不能很好地与C++标准库配合使用。很少有充分的理由来创建这样的反常类型。
你的例子有些误导你。
As(As&&)=delete;
通过删除移动构造函数,你使得构造一个带有As&&
的As
是非法的,即使复制构造函数可以调用,因为它需要对常量引用。
显示您正在寻找的行为的示例如下:
struct As
{
As()=default;
As(const As&)=default;
As& operator=(As&&)=delete;
As& operator=(const As&)=delete;
~As()=default;
};
我刚刚删除了移动构造函数的删除。 As
不会隐式声明 move 构造函数,因为它具有一堆其他用户声明的特殊函数*。如果对此示例运行测试,您将看到该类是可构造的,即使它没有移动构造函数也是如此。
现场演示
*具体而言,如果存在用户声明的复制构造函数、复制赋值运算符、移动赋值运算符或析构函数,则不会隐式声明移动构造函数。
is_copy_constructible
不需要类型是可移动的。 当它说
CopyConstructible 需求(除了 MoveConstructible) [copyconstructible]
这意味着要成为 CopyConstructible,该类必须满足 MoveConstructible 的要求,这些要求是
T u = rv; u is equivalent to the value of rv before the construction
T(rv) T(rv) is equivalent to the value of rv before the construction
rv’s state is unspecified. [ Note: rv must still meet the requirements of the
library component that is using it. The operations listed in those requirements
must work as specified whether rv has been moved from or not. — end note ]
除了 [可复制构造]
T u = v; the value of v is unchanged and is equivalent to u
T(v) the value of v is unchanged and is equivalent to T(v)
std::is_move_constructible<As>::value
是错误的原因是您有一个已删除的移动构造器,它禁止移动构造。需要有一个未删除的移动构造函数并满足 [moveconstructible] 才能为真。
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板元程序查找相似的连续类型名称
- 是否可以从int转换为enum类类型
- 构造函数正在调用一个使用当前类类型的函数
- 我应该使用什么来代替void作为变体中的替代类型之一
- 类中的字符串不命名类型