Page MenuHomePhorge

types.hpp
No OneTemporary

Size
6 KB
Referenced Files
None
Subscribers
None

types.hpp

/*******************************************************************************
*
* File: types.hpp
*
* Contents: Implementation of some basic convenience types.
*
* Copyright 2017
*
* Author: David Juhasz (david.juhasz@tuwien.ac.at)
*
* This implementation is partially based on the implementation of
* corresponding parts of CAF.
* TODO: Check license.
*
******************************************************************************/
#ifndef ROSA_SUPPORT_TYPES_HPP
#define ROSA_SUPPORT_TYPES_HPP
#include "rosa/support/debug.hpp"
#include <string>
namespace rosa {
/* ************************************************************************** *
* Unit *
* ************************************************************************** */
// Unit is analogous to void, but can be safely returned, stored, etc.
// to enable higher-order abstraction without cluttering code with
// exceptions for void (which can't be stored, for example).
struct UnitType {
constexpr UnitType() noexcept {
// nop
}
constexpr UnitType(const UnitType &) noexcept {
// nop
}
template <class T> explicit constexpr UnitType(T &&) noexcept {
// nop
}
template <class... Ts>
constexpr UnitType operator()(Ts &&...) const noexcept {
return {};
}
};
using unit_t = UnitType;
static constexpr unit_t unit = unit_t{}; // NOLINT
inline std::string to_string(const unit_t &) { return "unit"; }
template <typename T> struct LiftVoid { using Type = T; };
template <> struct LiftVoid<void> { using Type = unit_t; };
template <typename T> struct UnliftVoid { using Type = T; };
template <> struct UnliftVoid<unit_t> { using Type = void; };
/* ************************************************************************** *
* None *
* ************************************************************************** */
// Represents "nothing", e.g., for clearing an Optional by assigning none.
struct NoneType {
constexpr NoneType() {
// nop
}
constexpr explicit operator bool() const { return false; }
};
using none_t = NoneType;
static constexpr none_t none = none_t{}; // NOLINT
inline std::string to_string(const none_t &) { return "none"; }
/* ************************************************************************** *
* Optional *
* ************************************************************************** */
// A C++17 compatible optional implementation.
template <class T> class Optional {
public:
using Type = T;
// Creates an instance without value.
Optional(const none_t & = none) : Valid(false) {
// nop
}
// Creates an valid instance from value.
template <class U, class E = typename std::enable_if<
std::is_convertible<U, T>::value>::type>
Optional(U X) : Valid(false) {
cr(std::move(X));
}
Optional(const Optional &Other) : Valid(false) {
if (Other.Valid) {
cr(Other.Value);
}
}
Optional(Optional &&Other) noexcept(
std::is_nothrow_move_constructible<T>::value)
: Valid(false) {
if (Other.Valid) {
cr(std::move(Other.Value));
}
}
~Optional() { destroy(); }
Optional &operator=(const Optional &Other) {
if (Valid) {
if (Other.Valid) {
Value = Other.Value;
} else {
destroy();
}
} else if (Other.Valid) {
cr(Other.Value);
}
return *this;
}
Optional &operator=(Optional &&Other) noexcept(
std::is_nothrow_destructible<T>::value
&&std::is_nothrow_move_assignable<T>::value) {
if (Valid) {
if (Other.Valid) {
Value = std::move(Other.Value);
} else {
destroy();
}
} else if (Other.Valid) {
cr(std::move(Other.Value));
}
return *this;
}
// Checks whether this object contains a value.
explicit operator bool() const { return Valid; }
// Checks whether this object does not contain a value.
bool operator!() const { return !Valid; }
// Returns the value.
// PRE: Valid
T &operator*() {
ASSERT(Valid);
return Value;
}
// Returns the value.
// PRE: Valid
const T &operator*() const {
ASSERT(Valid);
return Value;
}
// Returns the value.
// PRE: Valid
const T *operator->() const {
ASSERT(Valid);
return &Value;
}
// Returns the value.
// PRE: Valid
T *operator->() {
ASSERT(Valid);
return &Value;
}
// Returns the value.
// PRE: Valid
T &value() {
ASSERT(Valid);
return Value;
}
// Returns the value.
// PRE: Valid
const T &value() const {
ASSERT(Valid);
return Value;
}
// Returns the value if Valid, otherwise returns DefaultValue.
const T &valueOr(const T &DefaultValue) const {
return Valid ? Value() : DefaultValue;
}
private:
void destroy() {
if (Valid) {
Value.~T();
Valid = false;
}
}
template <class V> void cr(V &&X) {
ASSERT(!Valid);
Valid = true;
new (&Value) T(std::forward<V>(X));
}
bool Valid;
union {
T Value;
};
};
// Template specialization to allow Optional to hold a reference
// rather than an actual value with minimal overhead.
template <typename T> class Optional<T &> {
public:
using Type = T;
Optional(const none_t & = none) : Value(nullptr) {
// nop
}
Optional(T &X) : Value(&X) {
// nop
}
Optional(T *X) : Value(X) {
// nop
}
Optional(const Optional &Other) = default;
Optional &operator=(const Optional &Other) = default;
explicit operator bool() const { return Value != nullptr; }
bool operator!() const { return !Value; }
T &operator*() {
ASSERT(Value);
return *Value;
}
const T &operator*() const {
ASSERT(Value);
return *Value;
}
T *operator->() {
ASSERT(Value);
return Value;
}
const T *operator->() const {
ASSERT(Value);
return Value;
}
T &value() {
ASSERT(Value);
return *Value;
}
const T &value() const {
ASSERT(Value);
return *Value;
}
const T &valueOr(const T &DefaultValue) const {
return Value ? Value() : DefaultValue;
}
private:
T *Value;
};
// Template specialization to allow Optional to implement a flag for void.
template <> class Optional<void> {
public:
using Type = unit_t;
Optional(none_t = none) : Value(false) {
// nop
}
Optional(unit_t) : Value(true) {
// nop
}
Optional(const Optional &Other) = default;
Optional &operator=(const Optional &Other) = default;
explicit operator bool() const { return Value; }
bool operator!() const { return !Value; }
private:
bool Value;
};
} // End namespace rosa
#endif // ROSA_SUPPORT_TYPES_HPP

File Metadata

Mime Type
text/x-c++
Expires
Wed, Jul 2, 12:07 PM (16 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157134
Default Alt Text
types.hpp (6 KB)

Event Timeline