在使用之前从 std::aligned_storage 派生一个指针在 C++ 中是否安全?

jac*_*bsa 5 c++ language-lawyer c++14 c++17 c++20

它是保证安全的C ++标准的指针,以获得Tstd::aligned_storage_t<sizeof(T), alignof(T)>之前的T实际创建本身?例如,以下是否合法?

std::aligned_storage_t<sizeof(T), alignof(T)> storage;
T* ptr = reinterpret_cast<T*>(&storage);  // Perhaps with std::launder?
new (&storage) T;

ptr->DoSomething();
Run Code Online (Sandbox Code Playgroud)

我希望参考有关为什么允许/不允许这样做的标准。我正在用 C++17 编写,但如果 C++20 中的答案不同,我仍然会感兴趣。

我希望这合法的原因是有效地实现一对承诺/未来类型,在值类型中具有协方差(因此Future<Animal>可以从 构造Promise<Cat>)。这是一个草图,其中包含所有 SFINAE 和同步以及其他细节:

template <typename T>
class Promise {
  private:
   // The storage in which we'll eventually construct our object once SetValue
   // is called. We don't just use a T object directly because we don't want
   // to require it to be default-constructible.
   std::aligned_storage_t<sizeof(T), alignof(T)> storage_;
   
   // Does storage_ contain a value yet?
   bool ready_ = false;
   
  public:
   void SetValue(T value) {
    new (&storage_) T(std::move(value));
    ready_ = true;
   }
};

template <typename T>
class Future {
  private:
   // A pointer that will eventually be valid.
   const T* const ptr_;

  public:
   // Create a future that can be used to access the value set on the supplied
   // promise.
   //
   // REQUIRES: U is T, or a subclass of T.
   template <typename U>
   Future(Promise<U>* promise)
       : ptr_(reinterpret_cast<U>(promise->storage_)) {}
   
   // REQUIRES: Promise::SetValue has been called.
   const T& Get() const { return *ptr_; }
}
Run Code Online (Sandbox Code Playgroud)