首页 > 解决方案 > 是否`std::any_cast` 要求 `T` 即使在要求指针时也是可构造的?

问题描述

我想std::any包含std::vector<std::unique_ptr<T>>.

class Foo {
 public:
  Foo() = default;
  ~Foo() = default;
  Foo(const Foo&) = default;
  Foo(Foo&&) = default;
  Foo& operator=(const Foo&) = default;
  Foo& operator=(Foo&&) = default;
  virtual void bar() = 0;
};

void f() {
  using std::any;
  using std::any_cast;
  using std::unique_ptr;
  using std::vector;
  using V = vector<unique_ptr<Foo>>;

  any a(V());
  V* v = any_cast<V>(&a);
}

根据文件std::any_cast<T>(&a)似乎要回来了V*。我认为这不会复制包含的对象。但是当我试图编译上面的代码时,我得到了以下错误:

/usr/include/c++/8/bits/stl_construct.h:75:7: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Foo; _Dp = std::default_delete<Foo>]’
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

这是否意味着std::any_cast<V>(&a)需要V可构造?是否std::any_cast复制包含的对象,即使它只是被要求提供一个指针?如果是这样,为什么需要复制内容?

标签: c++c++17std

解决方案


std::any使用类型擦除技术。这意味着在擦除类型时必须检测到对擦除类型施加的任何要求。这与模板类型不同,模板类型可以在您调用实际使用这些需求的函数时评估需求。

因此,即使您不做实际需要的事情,any仍然会施加这些要求。

话虽如此,在这种情况下,您正在做真正需要它的事情。即,any a(V());。它会将对象复制到a. 请记住:您不能通过函数参数进行复制省略。


推荐阅读