Maybe type implementation This supposed to implement a Maybe type that can either hold a value T or "nothing". It's designed to work well with vectors (that's why I take extra care to noexcept constructors whenever possible). I'm governing the actual data with ::std::aligned_storage. Note: The just member function is a reference to the Haskell Maybe data-constructor Just.

Did I miss anything?

#pragma once

#include &lt;utility&gt;
#include &lt;algorithm&gt;
#include &lt;type_traits&gt;

namespace ads {
  template &lt;typename T&gt;
  class Maybe {
    public:
      typedef typename ::std::aligned_storage&lt;sizeof(T),alignof(T)&gt;::type storage_type;
      typedef T value_type;
    private:
      storage_type data;
      bool is_valid;
      inline T* ptr() {
        return reinterpret_cast&lt;T*&gt;(&amp;data);
      }
      inline T const* ptr() const {
        return reinterpret_cast&lt;T const*&gt;(&amp;data);
      }
    public:
      Maybe() noexcept : data(), is_valid(false) {}
      template &lt;typename U&gt;
      Maybe(U&amp;&amp; v) noexcept(::std::is_nothrow_move_constructible&lt;T&gt;::value) : data(), is_valid(false) {
        create(::std::forward&lt;U&gt;(v));
      }
      Maybe(Maybe const&amp; from) noexcept(::std::is_nothrow_copy_constructible&lt;T&gt;::value) : data(), is_valid(false) {
        if (from.is_valid)
          create(*from.ptr());
      }
      Maybe(Maybe&amp;&amp; from) noexcept(::std::is_nothrow_move_constructible&lt;T&gt;::value) : data(), is_valid(false) {
        if (from.is_valid)
          create(::std::move(*from.ptr()));
      }
      template &lt;typename U&gt;
      Maybe&amp; operator=(U&amp;&amp; v) noexcept(::std::is_nothrow_move_constructible&lt;T&gt;::value &amp;&amp; ::std::is_nothrow_copy_constructible&lt;T&gt;::value &amp;&amp; ::std::is_nothrow_assignable&lt;T,U&gt;::value) {
        create(::std::forward&lt;U&gt;(v));
        return *this;
      }
      Maybe&amp; operator=(Maybe const&amp; from) noexcept(::std::is_nothrow_copy_constructible&lt;T&gt;::value &amp;&amp; ::std::is_nothrow_assignable&lt;T,T&gt;::value) {
        if (from.is_valid) {
          create(*from.ptr());
        } else {
          destroy();
        }
        return *this;
      }
      Maybe&amp; operator=(Maybe&amp;&amp; from) noexcept(::std::is_nothrow_move_constructible&lt;T&gt;::value &amp;&amp; ::std::is_nothrow_assignable&lt;T,T&gt;::value) {
        if (from.is_valid) {
          create(::std::move(*from.ptr()));
        } else {
          destroy();
        }
        return *this;
      }
      ~Maybe() noexcept(::std::is_nothrow_destructible&lt;T&gt;::value) {
        destroy();
      }

      bool valid() const noexcept {
        return is_valid;
      }
      operator T&amp;() noexcept {
        return *ptr();
      }
      operator T const&amp;() const noexcept {
        return *ptr();
      }
      T&amp; just() noexcept {
        return *ptr();
      }
      T const&amp; just() const noexcept {
        return *ptr();
      }

      template &lt;typename U&gt;
      void create(U&amp;&amp; v) noexcept(::std::is_nothrow_move_constructible&lt;T&gt;::value &amp;&amp; ::std::is_nothrow_copy_constructible&lt;T&gt;::value &amp;&amp; ::std::is_nothrow_assignable&lt;T,U&gt;::value){
        if (is_valid) {
          *ptr() = ::std::forward&lt;U&gt;(v);
        } else {
          new(&amp;data) T(::std::forward&lt;U&gt;(v));
          is_valid = true;
        }
      }
      void destroy() noexcept(::std::is_nothrow_destructible&lt;T&gt;::value) {
        if (is_valid) {
          ptr()-&gt;~T();
          is_valid = false;
        }
      }
  };
}
Creating holes in the type system:

operator T&amp; and it's const sibling is probably very undesirable conversion. Why, then, std::string doesn't have operator const char*()? The answer is a type system. It meant to be explicit. std::optional uses overloading of operator*() and operator-&gt;().

Don't pay for what you don't use:

I would expect constructor to not check for is_valid of itself, because it is obvious (you're calling create() from constructor, which does check for validity). In most cases this won't make a difference, but you still should strive for perfection.

Missing features:


swap
comparison operators
emplace
value_or, which is I think the most useful. Returns provided default value if there optional is not initialized yet. 
one function that throws when the optional is not initialized yet. just() is a great candidate.


Style:

You could enter a newline in some places where the line is long. 

I think that calling global std might be somewhat restricting. It is arguable, though.