Hol*_*Cat 7 c++ language-lawyer c++14 c++17
请原谅这个令人费解的标题,并考虑以下代码:
#include <memory>
#include <utility>
using X = std::unique_ptr<int>;
using A = std::pair<int, const X>;
using B = std::pair<int, X>;
static_assert(std::is_constructible<A, B>::value, "(1)"); // Ok.
static_assert(std::is_convertible<B, A>::value, "(2)"); // Rejected by GCC and Clang, in C++14 and before.
static_assert(std::is_constructible<const X, X>::value, "(3)"); // Ok.
static_assert(std::is_convertible<X, const X>::value, "(4)"); // Ok.
Run Code Online (Sandbox Code Playgroud)
简而言之,std::pair<int, const std::unique_ptr<int>>来自类型右值的构造函数std::pair<int, std::unique_ptr<int>>在explicitC++14、隐式和 C++17 及更新版本中。这种差异从何而来?
只有 libstdc++ 和 libc++ 演示了此行为。在MSVC的库中,构造函数总是隐式的。
为什么是explicit在 C++14 中?我没有看到任何与cppreference(构造函数(6))相关的内容。
C++17 之前也没有相关的构造函数explicit。
C++17 之前的模式中的 GCC 和 Clang 实际上正在考虑std::is_convertible<B, A>::valuefalse,因为A的移动构造函数被隐式删除。
移动构造函数被隐式删除,因为 aconst std::unique_ptr无法移动或复制。
在 C++17 之前需要实现移动构造函数std::is_convertible<B, A>::value,因为它测试以下形式的函数是否
A test() {
return std::declval<B>();
}
Run Code Online (Sandbox Code Playgroud)
将是格式良好的。return 语句复制初始化操作数的返回A值,在 C++17 之前,复制初始化总是涉及到目标类型临时对象的转换(如果需要),然后从临时对象直接初始化目标。该直接初始化将使用 的移动构造函数A。编译器可以删除移动,但移动构造函数必须仍然可用。
由于 C++17 强制复制省略适用,甚至从概念上讲,复制初始化不再包含通过移动构造函数的直接初始化。
| 归档时间: |
|
| 查看次数: |
193 次 |
| 最近记录: |