bsnes/nall/maybe.hpp
Tim Allen 3e807946b8 Update to v099r11 release.
byuu says:

Changelog:
- NES PPU core updated to use BitFields (absolutely massive improvement
  in code readability)
- NES APU core updated to new coding style
- NES cartridge/board and cartridge/chip updated to new coding style
- pushed NES PPU rendering one dot forward (doesn't fix King's Quest V
  yet, sadly)
- fixed SNES PPU BG tilemask for 128KiB VRAM mode (doesn't fix Yoshi's
  Island, though)

So ... I kind of went overboard with the fc/cartridge changes. This WIP
diff is 185KiB >_>
I didn't realize it was going to be as big a task as it was, but once
I started everything broke in a chain reaction, so I had to do it all
at once.

There's a massive chance we've broken a bunch of NES things. Any typos
in this WIP are going to be absolutely insidious to track down =(

But ... supposing I pulled it off, this means the Famicom core is now
fully converted to the new coding style as well. That leaves only the
GB and GBA cores. Once those are finished, then we'll finally be free
of these gigantic hellspawn diffs.
2016-06-27 23:07:57 +10:00

91 lines
3.3 KiB
C++

#pragma once
namespace nall {
struct nothing_t {};
static nothing_t nothing;
template<typename T>
struct maybe {
inline maybe() {}
inline maybe(nothing_t) {}
inline maybe(const T& source) { operator=(source); }
inline maybe(T&& source) { operator=(move(source)); }
inline maybe(const maybe& source) { operator=(source); }
inline maybe(maybe&& source) { operator=(move(source)); }
inline ~maybe() { reset(); }
inline auto operator=(nothing_t) -> maybe& { reset(); return *this; }
inline auto operator=(const T& source) -> maybe& { reset(); _valid = true; new(&_value.t) T(source); return *this; }
inline auto operator=(T&& source) -> maybe& { reset(); _valid = true; new(&_value.t) T(move(source)); return *this; }
inline auto operator=(const maybe& source) -> maybe& {
if(this == &source) return *this;
reset();
if(_valid = source._valid) new(&_value.t) T(source.get());
return *this;
}
inline auto operator=(maybe&& source) -> maybe& {
if(this == &source) return *this;
reset();
if(_valid = source._valid) new(&_value.t) T(move(source.get()));
return *this;
}
inline explicit operator bool() const { return _valid; }
inline auto reset() -> void { if(_valid) { _value.t.~T(); _valid = false; } }
inline auto data() -> T* { return _valid ? &_value.t : nullptr; }
inline auto get() -> T& { assert(_valid); return _value.t; }
inline auto data() const -> const T* { return ((maybe*)this)->data(); }
inline auto get() const -> const T& { return ((maybe*)this)->get(); }
inline auto operator->() -> T* { return data(); }
inline auto operator->() const -> const T* { return data(); }
inline auto operator*() -> T& { return get(); }
inline auto operator*() const -> const T& { return get(); }
inline auto operator()() -> T& { return get(); }
inline auto operator()() const -> const T& { return get(); }
inline auto operator()(const T& invalid) const -> const T& { return _valid ? get() : invalid; }
private:
union U {
T t;
U() {}
~U() {}
} _value;
bool _valid = false;
};
template<typename T>
struct maybe<T&> {
inline maybe() : _value(nullptr) {}
inline maybe(nothing_t) : _value(nullptr) {}
inline maybe(const T& source) : _value((T*)&source) {}
inline maybe(const maybe& source) : _value(source._value) {}
inline auto operator=(nothing_t) -> maybe& { _value = nullptr; return *this; }
inline auto operator=(const T& source) -> maybe& { _value = (T*)&source; return *this; }
inline auto operator=(const maybe& source) -> maybe& { _value = source._value; return *this; }
inline explicit operator bool() const { return _value; }
inline auto reset() -> void { _value = nullptr; }
inline auto data() -> T* { return _value; }
inline auto get() -> T& { assert(_value); return *_value; }
inline auto data() const -> const T* { return ((maybe*)this)->data(); }
inline auto get() const -> const T& { return ((maybe*)this)->get(); }
inline auto operator->() -> T* { return data(); }
inline auto operator->() const -> const T* { return data(); }
inline auto operator*() -> T& { return get(); }
inline auto operator*() const -> const T& { return get(); }
inline auto operator()() -> T& { return get(); }
inline auto operator()() const -> const T& { return get(); }
inline auto operator()(const T& invalid) const -> const T& { return _value ? get() : invalid; }
private:
T* _value;
};
}