移动构造函数为何对is_assignable的判断产生深远影响?

2026-04-16 18:401阅读0评论SEO教程
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计683个文字,预计阅读时间需要3分钟。

移动构造函数为何对is_assignable的判断产生深远影响?

刚刚来自 +is_assignable 和 std::unique_ptr。@Angew 告诉我,因为 std::unique_ptr、do_nothing 和 std::unique_ptr 是不同类型,所以 static_assert(不是 std::is_assignable 刚刚来自 is_assignable and std::unique_ptr. @Angew告诉我,因为std :: unique_ptr< int,do_nothing>和std :: unique_ptr< int>是不同的类型,所以static_assert(不是std :: is_assignable< std :: unique_ptr< int>,std :: unique_ptr< int,do_nothing>> :: value,“”);.所以,我尝试过:

template<typename T, typename D> struct MoveAssignOnly_V2 { MoveAssignOnly_V2& operator=(MoveAssignOnly_V2&) = delete; MoveAssignOnly_V2& operator=(MoveAssignOnly_V2&&) noexcept {} }; int main() { static_assert(not std::is_assignable_v<MoveAssignOnly_V2<int, float>, MoveAssignOnly_V2<int, double>>); }

是的,因为MoveAssignOnly_V2< int,float>和MoveAssignOnly_V2< int,double>是两种不同的类型,因此它们不可分配.

移动构造函数为何对is_assignable的判断产生深远影响?

但是,当我添加一个移动ctor时:

template<class U, class E> MoveAssignOnly_V2(MoveAssignOnly_V2<U, E>&& m) noexcept {}

static_assert fail!(包括gcc和clang).

问题:为什么移动构造函数会影响is_assignable?

更新

我添加这个构造函数的原因是我发现std :: unique_ptr有一个

template< class U, class E > unique_ptr( unique_ptr<U, E>&& u ) noexcept;

,这让我有点困惑:如果它有这样一个ctor,它怎么可能不可分配?所以我尝试将此类ctor添加到MoveAssignOnly_V2并发布此问题.这两个答案都很好,但是仍然无法解释为什么当std :: unique_ptr同时具有移动赋值和这个模板化构造函数时,它不可赋值.

拿这个代码:

MoveAssignOnly_V2<int, float> lhs; MoveAssignOnly_V2<int, double> rhs; lhs = stdL::move(rhs);

当转换构造函数(注意它不是移动构造函数)不存在时,无法将rhs分配给lhs.

但是,当您添加构造函数模板时,现在有一种方法可以将rhs转换为MoveAssignOnly_V2< int,float>类型. (创建该类型的临时).然后,可以从该临时值移动到lhs.

这与以下原则相同:

double lhs = 3.14; float rhs = 42.f; lhs = std::move(rhs);

要解决问题中的更新:

您不能单独使用功能声明,您必须阅读完整规范(在标准或suitable reference中).引用有关std :: unique_ptr的转换构造函数的链接引用:

This constructor only participates in overload resolution if all of the following is true:

a) unique_ptr<U, E>::pointer is implicitly convertible to pointer
b) U is not an array type
c) Either Deleter is a reference type and E is the same type as D, or Deleter is not a reference type and E is implicitly convertible to D

正如您所看到的,必须实现unique_ptr的转换构造函数,以便只有在源删除器可以转换为目标删除器时它才有效.这与上一个问题中的移动分配基本相同.

本文共计683个文字,预计阅读时间需要3分钟。

移动构造函数为何对is_assignable的判断产生深远影响?

刚刚来自 +is_assignable 和 std::unique_ptr。@Angew 告诉我,因为 std::unique_ptr、do_nothing 和 std::unique_ptr 是不同类型,所以 static_assert(不是 std::is_assignable 刚刚来自 is_assignable and std::unique_ptr. @Angew告诉我,因为std :: unique_ptr< int,do_nothing>和std :: unique_ptr< int>是不同的类型,所以static_assert(不是std :: is_assignable< std :: unique_ptr< int>,std :: unique_ptr< int,do_nothing>> :: value,“”);.所以,我尝试过:

template<typename T, typename D> struct MoveAssignOnly_V2 { MoveAssignOnly_V2& operator=(MoveAssignOnly_V2&) = delete; MoveAssignOnly_V2& operator=(MoveAssignOnly_V2&&) noexcept {} }; int main() { static_assert(not std::is_assignable_v<MoveAssignOnly_V2<int, float>, MoveAssignOnly_V2<int, double>>); }

是的,因为MoveAssignOnly_V2< int,float>和MoveAssignOnly_V2< int,double>是两种不同的类型,因此它们不可分配.

移动构造函数为何对is_assignable的判断产生深远影响?

但是,当我添加一个移动ctor时:

template<class U, class E> MoveAssignOnly_V2(MoveAssignOnly_V2<U, E>&& m) noexcept {}

static_assert fail!(包括gcc和clang).

问题:为什么移动构造函数会影响is_assignable?

更新

我添加这个构造函数的原因是我发现std :: unique_ptr有一个

template< class U, class E > unique_ptr( unique_ptr<U, E>&& u ) noexcept;

,这让我有点困惑:如果它有这样一个ctor,它怎么可能不可分配?所以我尝试将此类ctor添加到MoveAssignOnly_V2并发布此问题.这两个答案都很好,但是仍然无法解释为什么当std :: unique_ptr同时具有移动赋值和这个模板化构造函数时,它不可赋值.

拿这个代码:

MoveAssignOnly_V2<int, float> lhs; MoveAssignOnly_V2<int, double> rhs; lhs = stdL::move(rhs);

当转换构造函数(注意它不是移动构造函数)不存在时,无法将rhs分配给lhs.

但是,当您添加构造函数模板时,现在有一种方法可以将rhs转换为MoveAssignOnly_V2< int,float>类型. (创建该类型的临时).然后,可以从该临时值移动到lhs.

这与以下原则相同:

double lhs = 3.14; float rhs = 42.f; lhs = std::move(rhs);

要解决问题中的更新:

您不能单独使用功能声明,您必须阅读完整规范(在标准或suitable reference中).引用有关std :: unique_ptr的转换构造函数的链接引用:

This constructor only participates in overload resolution if all of the following is true:

a) unique_ptr<U, E>::pointer is implicitly convertible to pointer
b) U is not an array type
c) Either Deleter is a reference type and E is the same type as D, or Deleter is not a reference type and E is implicitly convertible to D

正如您所看到的,必须实现unique_ptr的转换构造函数,以便只有在源删除器可以转换为目标删除器时它才有效.这与上一个问题中的移动分配基本相同.