#pragma once
#include <type_traits>
#include <wtf/Optional.h>
#include <wtf/StdLibExtras.h>
namespace WTF {
template<
typename EnumType,
typename std::underlying_type<EnumType>::type constant = std::numeric_limits<typename std::underlying_type<EnumType>::type>::max()>
struct EnumMarkableTraits {
static_assert(std::is_enum<EnumType>::value, "");
using UnderlyingType = typename std::underlying_type<EnumType>::type;
constexpr static bool isEmptyValue(EnumType value)
{
return static_cast<UnderlyingType>(value) == constant;
}
constexpr static EnumType emptyValue()
{
return static_cast<EnumType>(constant);
}
};
template<typename IntegralType, IntegralType constant = 0>
struct IntegralMarkableTraits {
static_assert(std::is_integral<IntegralType>::value, "");
constexpr static bool isEmptyValue(IntegralType value)
{
return value == constant;
}
constexpr static IntegralType emptyValue()
{
return constant;
}
};
template<typename T, typename Traits>
class Markable {
public:
constexpr Markable()
: m_value(Traits::emptyValue())
{ }
constexpr Markable(WTF::nullopt_t)
: Markable()
{ }
constexpr Markable(T&& value)
: m_value(WTFMove(value))
{ }
constexpr Markable(const T& value)
: m_value(value)
{ }
template<typename... Args>
constexpr explicit Markable(std::in_place_t, Args&&... args)
: m_value(std::forward<Args>(args)...)
{ }
constexpr Markable(const Optional<T>& value)
: m_value(bool(value) ? *value : Traits::emptyValue())
{ }
constexpr Markable(Optional<T>&& value)
: m_value(bool(value) ? WTFMove(*value) : Traits::emptyValue())
{ }
constexpr explicit operator bool() const { return !Traits::isEmptyValue(m_value); }
void reset() { m_value = Traits::emptyValue(); }
constexpr const T& value() const& { return m_value; }
constexpr T& value() & { return m_value; }
constexpr T&& value() && { return WTFMove(m_value); }
constexpr const T* operator->() const { return std::addressof(m_value); }
constexpr T* operator->() { return std::addressof(m_value); }
constexpr const T& operator*() const& { return m_value; }
constexpr T& operator*() & { return m_value; }
operator Optional<T>() &&
{
if (bool(*this))
return WTFMove(m_value);
return WTF::nullopt;
}
operator Optional<T>() const&
{
if (bool(*this))
return m_value;
return WTF::nullopt;
}
private:
T m_value;
};
}
using WTF::Markable;
using WTF::IntegralMarkableTraits;
using WTF::EnumMarkableTraits;