is_assignable和std :: unique_ptr [英] is_assignable and std::unique_ptr

查看:98
本文介绍了is_assignable和std :: unique_ptr的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是来自gcc的测试文件,实时演示

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::is_assignable

如果表达式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.

std::declval :

template<class T>
typename std::add_rvalue_reference<T>::type declval() noexcept;

返回类型为T&&,除非T是(可能是cv限定的)void,在这种情况下,返回类型为T.

The return type is T&& unless T 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?

推荐答案

p1p2是不同的类型.与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_ptrs 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆