[英]Why does std::is_assignable return false with related pointer types?
[英]Why does move constructor affect is_assignable?
刚来自is_assignable和std :: unique_ptr 。 @Angew告诉我,因为std::unique_ptr<int, do_nothing>
和std::unique_ptr<int>
是不同的类型,所以static_assert(not 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>
是两种不同的类型,因此它们不可分配。
但是 ,当我添加一个移动ctor:
template<class U, class E>
MoveAssignOnly_V2(MoveAssignOnly_V2<U, E>&& m) noexcept {}
static_assert
失败! (包括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);
要解决问题中的更新:
您不能单独使用函数声明,您必须阅读完整的规范(在标准或合适的参考中 )。 引用有关std::unique_ptr
的转换构造函数的链接引用:
如果满足以下所有条件,则此构造函数仅参与重载解析:
a)
unique_ptr<U, E>::pointer
可以隐式转换为pointer
b)U
不是数组类型
c)Deleter
是引用类型,E
是与D
相同的类型,或者Deleter
不是引用类型,E
可以隐式转换为D
正如您所看到的,必须实现unique_ptr
的转换构造函数,以便只有在源删除器可以转换为目标删除器时才会激活它。 这与上一个问题中的移动分配基本相同。
你在这里添加的内容:
template<class U, class E>
MoveAssignOnly_V2(MoveAssignOnly_V2<U, E>&& m) noexcept {}
不仅是一个移动构造函数,而且是一个模板化的构造函数,可以从任何MoveAssignOnly_V2<U, E>
构造MoveAssignOnly_V2<T, D>
MoveAssignOnly_V2<U, E>
。
因此MoveAssignOnly_V2<int, float>
从MoveAssignOnly_V2<int, double>>
构造MoveAssignOnly_V2<int, float>
就可以了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.