add c++17 optional
This commit is contained in:
parent
eb993acd2a
commit
1deafa3ad1
2
Makefile
2
Makefile
|
@ -1,5 +1,5 @@
|
||||||
LINK.o = $(LINK.cc)
|
LINK.o = $(LINK.cc)
|
||||||
CXXFLAGS = -std=c++11 -g -Wall
|
CXXFLAGS = -std=c++14 -g -Wall
|
||||||
CCFLAGS = -g
|
CCFLAGS = -g
|
||||||
|
|
||||||
DUMP_OBJS = dumpobj.o disassembler.o zrdz_disassembler.o
|
DUMP_OBJS = dumpobj.o disassembler.o zrdz_disassembler.o
|
||||||
|
|
|
@ -145,9 +145,7 @@ bool simplify_expression(expression &e) {
|
||||||
* if force is true, treat OP_LOC records as OP_VAL (for omf)
|
* if force is true, treat OP_LOC records as OP_VAL (for omf)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// should return std::optional<uint32_t>...
|
optional<uint32_t> evaluate_expression(expression &e, bool force) {
|
||||||
|
|
||||||
uint32_t evaluate_expression(expression &e, bool force) {
|
|
||||||
std::vector<expr> tmp;
|
std::vector<expr> tmp;
|
||||||
for (const auto &t : e.stack) {
|
for (const auto &t : e.stack) {
|
||||||
if (t.tag == OP_LOC && force) {
|
if (t.tag == OP_LOC && force) {
|
||||||
|
@ -163,7 +161,7 @@ uint32_t evaluate_expression(expression &e, bool force) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp.size() == 1 && tmp.front().tag == OP_VAL) return tmp.front().value;
|
if (tmp.size() == 1 && tmp.front().tag == OP_VAL) return optional<uint32_t>(tmp.front().value);
|
||||||
return 0;
|
return optional<uint32_t>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "optional.h"
|
||||||
|
|
||||||
struct expr {
|
struct expr {
|
||||||
expr(int t = 0, uint32_t v = 0, uint32_t s = 0)
|
expr(int t = 0, uint32_t v = 0, uint32_t s = 0)
|
||||||
: tag(t), value(v), section(s)
|
: tag(t), value(v), section(s)
|
||||||
|
@ -25,7 +27,7 @@ struct expression {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t evaluate_expression(expression &e, bool force = false);
|
optional<uint32_t> evaluate_expression(expression &e, bool force = false);
|
||||||
|
|
||||||
bool simplify_expression(expression &e);
|
bool simplify_expression(expression &e);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
#ifndef __optional_h__
|
||||||
|
#define __optional_h__
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
class bad_optional_access : public std::exception {
|
||||||
|
public:
|
||||||
|
virtual const char* what() const noexcept {
|
||||||
|
return "bad optional access";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class optional {
|
||||||
|
public:
|
||||||
|
typedef T value_type;
|
||||||
|
|
||||||
|
optional() = default;
|
||||||
|
|
||||||
|
optional( const optional& other ) {
|
||||||
|
if (other._engaged) {
|
||||||
|
new (std::addressof(_data)) T(*other);
|
||||||
|
_engaged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
optional( const optional&& other ) {
|
||||||
|
if (other._engaged) {
|
||||||
|
new (std::addressof(_data)) T(std::move(*other));
|
||||||
|
_engaged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template < class U >
|
||||||
|
optional( const optional<U>& other ) {
|
||||||
|
if (other._engaged) {
|
||||||
|
new (std::addressof(_data)) T(*other);
|
||||||
|
_engaged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template < class U >
|
||||||
|
optional( optional<U>&& other ) {
|
||||||
|
if (other._engaged) {
|
||||||
|
new (std::addressof(_data)) T(std::move(*other));
|
||||||
|
_engaged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class U = T>
|
||||||
|
optional(U &&value) {
|
||||||
|
new(std::addressof(_data)) T(std::forward<U>(value));
|
||||||
|
_engaged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
~optional() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
constexpr explicit operator bool() const {
|
||||||
|
return _engaged;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool has_value() const {
|
||||||
|
return _engaged;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* these should throw ... */
|
||||||
|
constexpr T& value() & {
|
||||||
|
if (!_engaged) throw bad_optional_access();
|
||||||
|
return *reinterpret_cast<T*>(std::addressof(_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const T & value() const & {
|
||||||
|
if (!_engaged) throw bad_optional_access();
|
||||||
|
return *reinterpret_cast<const T*>(std::addressof(_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr T&& value() && {
|
||||||
|
if (!_engaged) throw bad_optional_access();
|
||||||
|
return *reinterpret_cast<T*>(std::addressof(_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const T&& value() const && {
|
||||||
|
if (!_engaged) throw bad_optional_access();
|
||||||
|
return *reinterpret_cast<const T*>(std::addressof(_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< class U >
|
||||||
|
constexpr T value_or( U&& default_value ) const& {
|
||||||
|
return bool(*this) ? **this : static_cast<T>(std::forward<U>(default_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
template< class U >
|
||||||
|
constexpr T value_or( U&& default_value ) && {
|
||||||
|
return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(default_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const T* operator->() const {
|
||||||
|
return reinterpret_cast<const T*>(std::addressof(_data));
|
||||||
|
}
|
||||||
|
constexpr T* operator->() {
|
||||||
|
return reinterpret_cast<T*>(std::addressof(_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const T& operator*() const& {
|
||||||
|
return *reinterpret_cast<const T*>(std::addressof(_data));
|
||||||
|
}
|
||||||
|
constexpr T& operator*() & {
|
||||||
|
return *reinterpret_cast<T*>(std::addressof(_data));
|
||||||
|
}
|
||||||
|
constexpr const T&& operator*() const&& {
|
||||||
|
return *reinterpret_cast<const T*>(std::addressof(_data));
|
||||||
|
}
|
||||||
|
constexpr T&& operator*() && {
|
||||||
|
return *reinterpret_cast<T*>(std::addressof(_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
if (_engaged) {
|
||||||
|
reinterpret_cast<const T*>(std::addressof(_data))->~T();
|
||||||
|
_engaged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _engaged = false;
|
||||||
|
typename std::aligned_storage<sizeof(T), alignof(T)>::type _data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue