例如,考虑以下代码:
因为 Bar 类是从 Foo 类派生而来,所以它没有移动构造函数。但是可以使用复制构造函数来构造它。我从另一个答案中了解到了选择复制构造函数的原因:
如果 y 是类型 S,则 std::move(y) 的类型为 S&&,与类型 S& 兼容。因此,S x(std::move(y)) 是完全有效的,并调用复制构造函数 S::S(const S&)。
因此,我理解了为什么右值“降级”为左值复制,因此为什么 std::is_move_constructible 返回 true。然而,有没有一种方法来检测一个类型是否真正可移动构造,而不包括复制构造函数?
#include <type_traits>
#include <iostream>
struct Foo
{
Foo() = default;
Foo(Foo&&) = delete;
Foo(const Foo&) noexcept
{
std::cout << "copy!" << std::endl;
};
};
struct Bar : Foo {};
static_assert(!std::is_move_constructible_v<Foo>, "Foo shouldn't be move constructible");
// This would error if uncommented
//static_assert(!std::is_move_constructible_v<Bar>, "Bar shouldn't be move constructible");
int main()
{
Bar bar {};
Bar barTwo { std::move(bar) };
// prints "copy!"
}
因为 Bar 类是从 Foo 类派生而来,所以它没有移动构造函数。但是可以使用复制构造函数来构造它。我从另一个答案中了解到了选择复制构造函数的原因:
如果 y 是类型 S,则 std::move(y) 的类型为 S&&,与类型 S& 兼容。因此,S x(std::move(y)) 是完全有效的,并调用复制构造函数 S::S(const S&)。
因此,我理解了为什么右值“降级”为左值复制,因此为什么 std::is_move_constructible 返回 true。然而,有没有一种方法来检测一个类型是否真正可移动构造,而不包括复制构造函数?
struct baz: foo { baz(baz const&) = default; baz(&& other): baz(other) {} };
顺便说一下,这种行为与您的bar
相同,但似乎您希望以某种方式得到不同的答案。 - Dietmar Kühl