TartanLlama/expected

Request for std::launder usage in C++17 and later

swan-gh opened this issue · 0 comments

I believe that using tl::expected with a class X that contains const member variables is undefined behaviour. The same can actually be said for some STL containers, such as std::vector! This is due to assumptions made by the compiler about the value held at the address of a const member variable. The paper on std::launder gives some really good examples about this (it even uses optional as an example), so I'll let it do the explaining.

It more or less comes down to the usage of placement new and accessing the object at that address. Whenever the object (at the address passed to placement new) is accessed, it needs to be accessed through the pointer returned by std::launder. As an example, when the destructor gets invoked here:

~expected_storage_base() {
    if (m_has_val) {
      m_val.~T();
    } else {
      m_unexpect.~unexpected<E>();
    }
  }

It's my understanding that this would need to be replaced with:
std::launder(&m_val)->~T();
The same applies for tl::optional, I believe :) thank you for the great work you've done on both of these!