is_assignable和std :: unique_ptr [英] is_assignable and std::unique_ptr
问题描述
Here is a test file from gcc, live demo
struct do_nothing
{
template <class T>
void operator()(T*) {}
};
int
main()
{
int i = 0;
std::unique_ptr<int, do_nothing> p1(&i);
std::unique_ptr<int> p2;
static_assert(!std::is_assignable<decltype(p2), decltype(p1)>::value, ""); // note ! here.
}
如果表达式
std::declval<T>() = std::declval<U>()
在未求值的上下文中格式正确,则提供等于true的成员常量值.否则,值为false.就像从与这两种类型都不相关的上下文中一样执行访问检查.
If the expression
std::declval<T>() = std::declval<U>()
is well-formed in unevaluated context, provides the member constant value equal true. Otherwise, value is false. Access checks are performed as if from a context unrelated to either type.
template<class T>
typename std::add_rvalue_reference<T>::type declval() noexcept;
返回类型为
T&&
,除非T
是(可能是cv限定的)void,在这种情况下,返回类型为T.
The return type is
T&&
unlessT
is (possibly cv-qualified) void, in which case the return type is T.
让我们看看MoveAssignOnly
:
struct MoveAssignOnly {
MoveAssignOnly &operator=(MoveAssignOnly &) = delete;
MoveAssignOnly &operator=(MoveAssignOnly &&) = default;
};
int main()
{
static_assert(
not std::is_assignable<MoveAssignOnly, MoveAssignOnly>::value, "");
}
实时演示:
error: static_assert failed due to requirement '!std::is_assignable<MoveAssignOnly, MoveAssignOnly>::value'
是的,由于提供了移动分配而无法编译
让我们返回到 std::unique_ptr
也具有移动分配.
Let's return to the gcc's test file and std::unique_ptr
. As we know, std::unique_ptr
also has move assignments.
但是,与struct MoveAssignOnly
不同,static_assert(!std::is_assignable<decltype(p2), decltype(p1)>::value, "");
(更清楚的是,static_assert(!std::is_assignable<std::unique_ptr<int>, std::unique_ptr<int, do_nothing>>::value, "");
可以快乐地编译.
However, unlike struct MoveAssignOnly
, static_assert(!std::is_assignable<decltype(p2), decltype(p1)>::value, "");
(more clearly, static_assert(!std::is_assignable<std::unique_ptr<int>, std::unique_ptr<int, do_nothing>>::value, "");
compiles happily.
我一直在努力解决libcxx实现unique_ptr
的问题,但仍然无法弄清楚:当std::unique_ptr
提供移动分配时,std::unique_ptr
如何不可分配(! is_assignable
) ?
I have struggled with libcxx's implementation of unique_ptr
for long time, but still cannot figure out: how can std::unique_ptr
be not assignable(! is_assignable
) when std::unique_ptr
provides move assignments?
推荐答案
p1
和p2
是不同的类型.与shared_ptr
不同,unique_ptr
的删除器是指针类型的一部分.这意味着移动分配运算符不允许您在两个unique_ptr
的删除器类型不同的情况下进行分配(甚至移动分配).
p1
and p2
are of a different type. Unlike with shared_ptr
, the deleter of a unique_ptr
is part of the pointer's type. This means the move assignment operator does not allow you to assign (even move-assign) between two unique_ptr
s if their deleter types differ.
unique_ptr
还提供了一个赋值运算符模板,该模板允许从unique_ptr
的右值进行赋值,并使用其他删除器进行赋值,但这些删除器必须是可分配的(请参见
unique_ptr
also offers an assignment operator template which allows assigning from an rvalue of unique_ptr
with a different deleter, but the deleters must be assignable (see reference). So you can make your static assert fire by making the deleters assignable:
struct do_nothing
{
template <class T>
void operator()(T*) {}
template <class T>
operator std::default_delete<T>() { return {}; }
};
int
main()
{
int i = 0;
std::unique_ptr<int, do_nothing> p1(&i);
std::unique_ptr<int> p2;
static_assert(!std::is_assignable<decltype(p2), decltype(p1)>::value, ""); // note ! here.
}
这篇关于is_assignable和std :: unique_ptr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!