void test_optional(){
  using namespace faint;

  // Helper constants for testing the Optional
  const IntSize altSize = IntSize(5,5);
  const IntSize bmpSize = IntSize(10,10);
  const Bitmap alt(altSize);
  const Bitmap bmp(bmpSize);
  VERIFY(alt.GetSize() != bmp.GetSize());

  // Uninitialized optional (not set).
  Optional<Bitmap> optional;
  VERIFY(optional.NotSet());
  VERIFY(!optional.IsSet());
  VERIFY(!optional);

  static_assert(is_true<decltype(has_or(optional))>(),
    "Optional of value type lacks Or-method");
  EQUAL(optional.Or(alt).GetSize(), altSize);
  optional.IfSet(FAIL_IF_CALLED());
  optional.Visit(FAIL_IF_CALLED(), FAIL_UNLESS_CALLED());

  optional.Set(bmp);
  VERIFY(!optional.NotSet());
  VERIFY(optional.IsSet());
  VERIFY(optional);
  EQUAL(optional.Or(alt).GetSize(), bmpSize);
  optional.IfSet(FAIL_UNLESS_CALLED());
  optional.Visit(FAIL_UNLESS_CALLED(), FAIL_IF_CALLED());
  IntSize sz = optional.VisitSimple(
    [](const Bitmap& bmp){
      return bmp.GetSize();
    },
    alt.GetSize());
  EQUAL(sz, bmpSize);
  EQUAL(optional.Get().GetSize(), bmpSize);

  // Take the object (clearing the optional)
  Bitmap bmp2 = optional.Take();
  EQUAL(bmp2.GetSize(), bmp.GetSize());
  VERIFY(optional.NotSet());

  // Initializing construction
  Optional<Bitmap> optional2(bmp2);
  VERIFY(optional2.IsSet());
  EQUAL(optional2.Get().GetSize(), bmp.GetSize());
  optional2.Clear();
  VERIFY(optional2.NotSet());

  // Reference
  int i = 7;
  Optional<int&> oi(i);
  oi.Get() = 8;

  EQUAL(i, 8);
  static_assert(is_false<decltype(has_or(oi))>(),
    "Optional of reference type has Or-method.");

  // Non-reference
  int j = 7;
  Optional<int> oj(j);
  oj.Get() = 8;
  EQUAL(j, 7);

  // Ensure that copying a reference-Optional
  // does not copy the contained value.
  FailIfCopied f(10);
  Optional<FailIfCopied&> o(f);
  o.Get().value++;
  EQUAL(o.Get().value, 11);

  Optional<FailIfCopied&> o2(o);
  VERIFY(o2.IsSet());
  o2.Get().value++;
  EQUAL(o.Get().value, 12);

  IntHolder h(12);
  EQUAL(h.value, 12);
  h.Get(true).Get()++;
  EQUAL(h.value, 13);
  EQUAL(h.Get(true).Get(), 13);
}