11

我本来希望这个静态断言会触发:

#include <type_traits>
#include <memory>

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

但事实并非如此。

使用 MSVC12 编译:

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

4

2 回答 2

15

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

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

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

回应是:

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

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

请注意,断言会在使用最新版本的 Visual Studio 的 web 编译器上触发。最后一次更新是在Dec 3, 2015. 断言还会在 clang(实时查看)和 gcc 上触发。

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

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

那里的回应是:

感谢您报告此错误。我们已经修复了它,并且在 VS 2015 Preview 中提供了修复。

不清楚,这是在哪个版本的 Visual Studio 中修复的。一个回复说 2013 年末版本,而后者说 2015 预览版。

于 2015-12-07T14:12:10.590 回答
0

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

#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 中错误的好方法,即使对于您自己的类也是如此。因为如果您声明赋值运算符按值接受参数,那么您不能在同一个类中声明移动赋值(由于不明确的重载,任何移动赋值都不会编译)。

PS修复分配的关键思想来自这个相关的答案

于 2018-03-04T07:25:24.777 回答