问题 为什么is_copy_constructible在MSVC12中对unique_ptr返回true


我原以为这个静态断言会被激发:

#include <type_traits>
#include <memory>

int main() {
  static_assert(std::is_copy_constructible<std::unique_ptr<int>>::value, "UPtr has copy constructor?");
}

但事实并非如此。

使用MSVC12编译:

用于x64的Microsoft(R)C / C ++优化编译器版本18.00.31101


4262
2017-12-07 14:01


起源

奇。在GCC 5(Linux)上,断言触发。 - hlt
它失败了g ++: coliru.stacked-crooked.com/a/d0592d5e7824f2cd - NathanOliver
失败了 webcompiler 据我所知,这是相对最新的视觉工作室。 - Shafik Yaghmour
很公平,只是我们版本上的编译器错误然后!不幸的是我们不能只升级。容易解决,但它似乎很奇怪。 - sji
@RichardHodges我喜欢我工作的地方谢谢。请注意,在您侮辱其他人的工作场所之前,可能有充分的理由不立即进行升级。 - sji


答案:


static_assert 应该开火, 的std ::的unique_ptr 有一个隐式删除的复制构造函数,所以这是一个错误。这看起来与此错误报告有关 std :: is_copy_constructible已损坏

(1)对于已删除的类型,std :: is_copy_constructible返回true   复制构造函数。

(2)对于组成的类型,std :: is_copy_constructible返回true   不可复制构造的类型。

而回应是:

感谢您报告此错误。我们已修复它,修复程序将在2013年后的Visual Studio的下一个主要版本中提供。

另外,请参阅此错误报告: std :: is_copy_constructible无法正常工作

请注意断言触发 webcompiler 这是使用最新版本的Visual Studio。上次更新已开启 Dec 3, 2015。断言也发出铿锵声(看到它)和gcc。

我发现了一个错误报告: std :: is_copy_constructible的奇怪行为 它与你的代码非常相似:

static_assert(std::is_copy_constructible<std::unique_ptr<int>>::value, "");

那里的回应是:

感谢您报告此错误。我们已经修好了,解决方法就是   在VS 2015 Preview中可用。

不清楚,修复了哪个版本的Visual Studio。一个回复说明2013年末版本,而后一个版本说2015预览版。


15
2017-12-07 14:12



不知道那个网络编译器。将是一个方便的工具谢谢。 - sji
“std :: unique_ptr既不是CopyConstructible也不是CopyAssignable” - 让我们不要将CopyConstructible和CopyAssignable(概念)与is_copy_constructible等检查混淆。前者比后者强得多。 - T.C.
@ T.C。我知道这可能会让人感到困惑,修复。 - Shafik Yaghmour


以下是使类不可复制的四种方法:

#include <stdio.h>
#include <type_traits>

class A {
public:
    A(const A&) = delete;
    void operator=(const A&) = delete;
};

class B {
private:
    B(const B&) = delete;
    void operator=(const B&) = delete;
};

class C {
public:
    C(const C&) = delete;
    void operator=(const C&) = delete;
    void operator=(C) = delete;
};

class D {
private:
    D(const D&) = delete;
    void operator=(const D&) = delete;
    void operator=(D) = delete;
};

int main() {
    printf("%d %d\n", std::is_copy_constructible<A>::value, std::is_copy_assignable<A>::value);
    printf("%d %d\n", std::is_copy_constructible<B>::value, std::is_copy_assignable<B>::value);
    printf("%d %d\n", std::is_copy_constructible<C>::value, std::is_copy_assignable<C>::value);
    printf("%d %d\n", std::is_copy_constructible<D>::value, std::is_copy_assignable<D>::value);
}

在MSVC2013 x64(18.00.40629 for x64),它打印:

1 1    //A
0 1    //B
1 0    //C
0 0    //D

在适当的编译器上,所有八个值必须为零。

不幸的是,这样做  提供一种解决MSVC2013中的错误的好方法,即使对于您自己的类也是如此。因为如果声明赋值运算符按值接受参数,则不能在同一个类中声明移动赋值(由于模糊的重载,任何移动赋值都不会编译)。

附: 修复作业的关键思想来自于 这个相关的答案


0
2018-03-04 07:25