blob: 264b45ed616936fddd1284997a7c3ff21520e711 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef Optional_h
#define Optional_h
#include "wtf/Alignment.h"
#include "wtf/Assertions.h"
#include "wtf/Noncopyable.h"
#include "wtf/StdLibExtras.h"
#include "wtf/Utility.h"
namespace WTF {
// This is a lightweight template similar to std::experimental::optional.
// It currently does not support assignment, swapping, comparison, etc.
//
// Use this instead of OwnPtr for cases where you only want to conditionally
// construct a "scope" object.
//
// Example:
// Optional<DrawingRecorder> recorder;
// if (shouldDraw)
// recorder.emplace(constructor, args, here);
// // recorder destroyed at end of scope
//
// Note in particular that unlike a pointer, though, dereferencing a const
// optional yields a const reference.
template <typename T>
class Optional {
WTF_MAKE_NONCOPYABLE(Optional);
public:
Optional() : m_ptr(nullptr) { }
~Optional()
{
if (m_ptr)
m_ptr->~T();
}
typedef T* Optional::*UnspecifiedBoolType;
operator UnspecifiedBoolType() const { return m_ptr ? &Optional::m_ptr : nullptr; }
T& operator*() { ASSERT_WITH_SECURITY_IMPLICATION(m_ptr); return *m_ptr; }
const T& operator*() const { ASSERT_WITH_SECURITY_IMPLICATION(m_ptr); return *m_ptr; }
T* operator->() { ASSERT_WITH_SECURITY_IMPLICATION(m_ptr); return m_ptr; }
const T* operator->() const { ASSERT_WITH_SECURITY_IMPLICATION(m_ptr); return m_ptr; }
template <typename... Args>
void emplace(Args&&... args)
{
RELEASE_ASSERT(!m_ptr);
m_ptr = reinterpret_cast_ptr<T*>(&m_storage.buffer);
new (m_ptr) T(forward<Args>(args)...);
}
private:
T* m_ptr;
AlignedBuffer<sizeof(T), WTF_ALIGN_OF(T)> m_storage;
};
} // namespace WTF
using WTF::Optional;
#endif // Optional_h