add c++17 optional

This commit is contained in:
Kelvin Sherlock 2017-01-08 20:17:10 -05:00
parent eb993acd2a
commit 1deafa3ad1
4 changed files with 146 additions and 7 deletions

View File

@ -1,5 +1,5 @@
LINK.o = $(LINK.cc)
CXXFLAGS = -std=c++11 -g -Wall
CXXFLAGS = -std=c++14 -g -Wall
CCFLAGS = -g
DUMP_OBJS = dumpobj.o disassembler.o zrdz_disassembler.o

View File

@ -145,9 +145,7 @@ bool simplify_expression(expression &e) {
* if force is true, treat OP_LOC records as OP_VAL (for omf)
*/
// should return std::optional<uint32_t>...
uint32_t evaluate_expression(expression &e, bool force) {
optional<uint32_t> evaluate_expression(expression &e, bool force) {
std::vector<expr> tmp;
for (const auto &t : e.stack) {
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;
return 0;
if (tmp.size() == 1 && tmp.front().tag == OP_VAL) return optional<uint32_t>(tmp.front().value);
return optional<uint32_t>();
}

View File

@ -4,6 +4,8 @@
#include <stdint.h>
#include <vector>
#include "optional.h"
struct expr {
expr(int t = 0, uint32_t v = 0, uint32_t s = 0)
: 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);

139
optional.h Normal file
View File

@ -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