Is it safe in C++ to derive a pointer from std::aligned_storage before using it?

Viewed 92

Is it guaranteed to be safe by the C++ standard to derive a pointer to T from std::aligned_storage_t<sizeof(T), alignof(T)> before the T itself is actually created? For example, is the following legal?

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

ptr->DoSomething();

I would appreciate references to the standard about why this is allowed/not allowed. I'm writing in C++17, but would still be interested if the answer is different in C++20.

The reason I want this to be legal is to efficiently implement a pair of promise/future types, with covariance in the value type (so Future<Animal> can be constructed from Promise<Cat>). Here is a sketch of what that might look like, with all the SFINAE and synchronization and other details stripped:

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_; }
}
0 Answers
Related