mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-09-13 22:47:15 -04:00
Prototype of std::expected
This commit is contained in:
parent
cf43087848
commit
ac602e40ed
@ -26,6 +26,11 @@ constexpr T&& forward(typename remove_reference<T>::type& t ){
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T&& forward(typename remove_reference<T>::type&& t ){
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
template<typename InputIterator, typename OutputIterator>
|
||||
void copy(OutputIterator out, InputIterator it, InputIterator end){
|
||||
if(it != end){
|
||||
|
24
tstl/include/conditional.hpp
Normal file
24
tstl/include/conditional.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
//=======================================================================
|
||||
// Copyright Baptiste Wicht 2013-2014.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#ifndef CONDITIONAL_H
|
||||
#define CONDITIONAL_H
|
||||
|
||||
namespace std {
|
||||
|
||||
template<bool B, typename If, typename Else>
|
||||
struct conditional {};
|
||||
|
||||
template<typename If, typename Else>
|
||||
struct conditional<true, If, Else> { typedef If type; };
|
||||
|
||||
template<typename If, typename Else>
|
||||
struct conditional<false, If, Else> { typedef Else type; };
|
||||
|
||||
} //end of namespace std
|
||||
|
||||
#endif
|
355
tstl/include/expected.hpp
Normal file
355
tstl/include/expected.hpp
Normal file
@ -0,0 +1,355 @@
|
||||
//=======================================================================
|
||||
// Copyright Baptiste Wicht 2013-2014.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#ifndef EXPECTED_H
|
||||
#define EXPECTED_H
|
||||
|
||||
#include "types.hpp"
|
||||
#include "algorithms.hpp"
|
||||
#include "conditional.hpp"
|
||||
#include "type_traits.hpp"
|
||||
#include "utility.hpp"
|
||||
#include "memory.hpp"
|
||||
#include "new.hpp"
|
||||
|
||||
namespace std {
|
||||
|
||||
constexpr struct only_set_valid_t {} only_set_valid;
|
||||
|
||||
template <typename E>
|
||||
struct exceptional {
|
||||
typedef E error_type;
|
||||
|
||||
error_type error;
|
||||
|
||||
exceptional(): error() {
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
explicit exceptional(error_type e) : error(e) {
|
||||
//Nothing else to init
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename E>
|
||||
union trivial_expected_storage {
|
||||
typedef T value_type;
|
||||
typedef E error_type;
|
||||
|
||||
error_type error;
|
||||
value_type value;
|
||||
|
||||
constexpr trivial_expected_storage() : value(){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
constexpr trivial_expected_storage(const exceptional<error_type>& e) : error(e.error){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
constexpr trivial_expected_storage(Args&&... args): value(std::forward<Args>(args)...){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
~trivial_expected_storage() = default;
|
||||
};
|
||||
|
||||
template<typename T, typename E>
|
||||
union non_trivial_expected_storage {
|
||||
typedef T value_type;
|
||||
typedef E error_type;
|
||||
|
||||
error_type error;
|
||||
value_type value;
|
||||
|
||||
constexpr non_trivial_expected_storage() : value(){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
constexpr non_trivial_expected_storage(exceptional<error_type>& e) : error(e.error){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
constexpr non_trivial_expected_storage(Args&&... args): value(std::forward<Args>(args)...){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
~non_trivial_expected_storage() {};
|
||||
};
|
||||
|
||||
template<typename T, typename E>
|
||||
struct trivial_expected_base {
|
||||
typedef T value_type;
|
||||
typedef E error_type;
|
||||
|
||||
bool has_value;
|
||||
trivial_expected_storage<T, E> storage;
|
||||
|
||||
trivial_expected_base() : has_value(true), storage(){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
trivial_expected_base(only_set_valid_t, bool hv) : has_value(hv){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
trivial_expected_base(const value_type& v) : has_value(true), storage(v){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
trivial_expected_base(value_type&& v) : has_value(true), storage(std::forward<value_type>(v)){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
trivial_expected_base(const exceptional<error_type>& e) : has_value(false), storage(e) {
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
~trivial_expected_base() = default;
|
||||
};
|
||||
|
||||
template<typename T, typename E>
|
||||
struct non_trivial_expected_base {
|
||||
typedef T value_type;
|
||||
typedef E error_type;
|
||||
|
||||
bool has_value;
|
||||
trivial_expected_storage<T, E> storage;
|
||||
|
||||
non_trivial_expected_base() : has_value(true), storage(){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
non_trivial_expected_base(only_set_valid_t, bool hv) : has_value(hv){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
non_trivial_expected_base(const value_type& v) : has_value(true), storage(v){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
non_trivial_expected_base(value_type&& v) : has_value(true), storage(std::forward<value_type>(v)){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
non_trivial_expected_base(const exceptional<error_type>& e) : has_value(false), storage(e) {
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
~non_trivial_expected_base(){
|
||||
if(has_value){
|
||||
storage.error.~value_type();
|
||||
} else {
|
||||
storage.error.~error_type();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
using expected_base = typename std::conditional<
|
||||
std::is_trivially_destructible<T>::value && std::is_trivially_destructible<E>::value,
|
||||
trivial_expected_base<T, E>,
|
||||
non_trivial_expected_base<T, E>
|
||||
>::type;
|
||||
|
||||
template<typename T, typename E = size_t>
|
||||
struct expected : expected_base<T, E> {
|
||||
typedef T value_type;
|
||||
typedef E error_type;
|
||||
|
||||
typedef expected<T, E> this_type;
|
||||
typedef expected_base<T, E> base_type;
|
||||
|
||||
private:
|
||||
value_type* value_ptr() {
|
||||
return std::addressof(base_type::storage.value);
|
||||
}
|
||||
|
||||
constexpr const value_type* value_ptr() const {
|
||||
return std::static_addressof(base_type::storage.value);
|
||||
}
|
||||
|
||||
error_type* error_ptr() {
|
||||
return std::addressof(base_type::storage.error);
|
||||
}
|
||||
|
||||
constexpr const error_type* error_ptr() const {
|
||||
return static_addressof(base_type::storage.error);
|
||||
}
|
||||
|
||||
constexpr const bool& contained_has_value() const& {
|
||||
return base_type::has_value;
|
||||
}
|
||||
|
||||
bool& contained_has_value() & {
|
||||
return base_type::has_value;
|
||||
}
|
||||
|
||||
bool&& contained_has_value() && {
|
||||
return std::move(base_type::has_value);
|
||||
}
|
||||
|
||||
constexpr const value_type& contained_value() const& {
|
||||
return base_type::storage.value;
|
||||
}
|
||||
|
||||
value_type& contained_value() & {
|
||||
return base_type::storage.value;
|
||||
}
|
||||
|
||||
value_type&& contained_value() && {
|
||||
return std::move(base_type::storage.value);
|
||||
}
|
||||
|
||||
constexpr const error_type& contained_error() const& {
|
||||
return base_type::storage.error;
|
||||
}
|
||||
|
||||
error_type& contained_error() & {
|
||||
return base_type::storage.error;
|
||||
}
|
||||
|
||||
error_type&& contained_error() && {
|
||||
return std::move(base_type::storage.error);
|
||||
}
|
||||
|
||||
public:
|
||||
/* Constructors */
|
||||
|
||||
constexpr expected(const value_type& v) : base_type(v){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
constexpr expected(value_type&& v) : base_type(std::forward<value_type>(v)){
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
expected(const expected& rhs) : base_type(only_set_valid, rhs.valid()) {
|
||||
if(rhs.valid()){
|
||||
::new (value_ptr()) value_type(rhs.contained_value());
|
||||
} else {
|
||||
::new (error_ptr()) error_type(rhs.contained_error());
|
||||
}
|
||||
}
|
||||
|
||||
expected(expected&& rhs) : base_type(only_set_valid, rhs.valid()) {
|
||||
if(rhs.valid()){
|
||||
new (value_ptr()) value_type(std::move(rhs.contained_value()));
|
||||
} else {
|
||||
new (error_ptr()) error_type(std::move(rhs.contained_error()));
|
||||
}
|
||||
}
|
||||
|
||||
expected(const exceptional<error_type>& e) : base_type(e) {
|
||||
//Nothing else to init
|
||||
}
|
||||
|
||||
expected() : base_type() {}
|
||||
|
||||
~expected() = default;
|
||||
|
||||
/* Operators */
|
||||
expected& operator=(const expected& rhs){
|
||||
this_type(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
expected& operator=(expected&& rhs){
|
||||
this_type(std::forward(rhs)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
expected& operator=(const value_type& v){
|
||||
this_type(v).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
expected& operator=(value_type&& v){
|
||||
this_type(std::forward(v)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Swap */
|
||||
|
||||
void swap(expected& rhs){
|
||||
if (valid()){
|
||||
if (rhs.valid()){
|
||||
std::swap(contained_value(), rhs.contained_value());
|
||||
} else {
|
||||
error_type t = std::move(rhs.contained_error());
|
||||
new (rhs.value_ptr()) value_type(std::move(contained_value()));
|
||||
new (error_ptr()) error_type(t);
|
||||
std::swap(contained_has_value(), rhs.contained_has_value());
|
||||
}
|
||||
} else {
|
||||
if (rhs.valid()){
|
||||
rhs.swap(*this);
|
||||
} else {
|
||||
std::swap(contained_error(), rhs.contained_error());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Accessors */
|
||||
|
||||
constexpr bool valid() const {
|
||||
return contained_has_value();
|
||||
}
|
||||
|
||||
constexpr explicit operator bool() const {
|
||||
return valid();
|
||||
}
|
||||
|
||||
constexpr const value_type& value() const {
|
||||
return contained_value();
|
||||
}
|
||||
|
||||
constexpr const value_type& operator*() const {
|
||||
return contained_value();
|
||||
}
|
||||
|
||||
value_type& operator*(){
|
||||
return contained_value();
|
||||
}
|
||||
|
||||
constexpr const value_type* operator->() const {
|
||||
return value_ptr();
|
||||
}
|
||||
|
||||
value_type* operator->(){
|
||||
return value_ptr();
|
||||
}
|
||||
|
||||
constexpr const error_type& error() const {
|
||||
return contained_error();
|
||||
}
|
||||
|
||||
constexpr exceptional<error_type> get_exceptional() const {
|
||||
return exceptional<error_type>(contained_error());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline expected<T> make_expected(T&& v){
|
||||
return expected<T>(std::forward<T>(v));
|
||||
}
|
||||
|
||||
template<typename T, typename U, typename E>
|
||||
inline expected<T, U> make_expected_from_error(E v){
|
||||
return expected<T, U>(exceptional<U>(v));
|
||||
}
|
||||
|
||||
template<typename T, typename E>
|
||||
inline expected<T, E> make_expected_from_error(E v){
|
||||
return expected<T, E>(exceptional<E>(v));
|
||||
}
|
||||
|
||||
} //end of namespace std
|
||||
|
||||
#endif
|
52
tstl/include/memory.hpp
Normal file
52
tstl/include/memory.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
//=======================================================================
|
||||
// Copyright Baptiste Wicht 2013-2014.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#ifndef MEMORY_H
|
||||
#define MEMORY_H
|
||||
|
||||
#include "enable_if.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace std {
|
||||
|
||||
template< class T >
|
||||
T* addressof(T& arg){
|
||||
return reinterpret_cast<T*>(
|
||||
&const_cast<char&>(
|
||||
reinterpret_cast<const volatile char&>(arg)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct has_overloaded_addressof {
|
||||
template <class X>
|
||||
static constexpr bool has_overload(...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class X, size_t S = sizeof(std::declval<X&>().operator&()) >
|
||||
static constexpr bool has_overload(bool) {
|
||||
return true;
|
||||
}
|
||||
|
||||
constexpr static bool value = has_overload<T>(true);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr typename std::disable_if<has_overloaded_addressof<T>::value, T*>::type
|
||||
static_addressof(T& ref){
|
||||
return &ref;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr typename std::enable_if<has_overloaded_addressof<T>::value, T*>::type
|
||||
static_addressof(T& ref){
|
||||
return std::addressof(ref);
|
||||
}
|
||||
|
||||
} //end of namespace std
|
||||
|
||||
#endif
|
19
tstl/include/new.hpp
Normal file
19
tstl/include/new.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
//=======================================================================
|
||||
// Copyright Baptiste Wicht 2013-2014.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#ifndef NEW_H
|
||||
#define NEW_H
|
||||
|
||||
inline void* operator new( size_t , void* place){
|
||||
return place;
|
||||
}
|
||||
|
||||
inline void* operator new[]( size_t , void* place){
|
||||
return place;
|
||||
}
|
||||
|
||||
#endif
|
50
tstl/include/type_traits.hpp
Normal file
50
tstl/include/type_traits.hpp
Normal file
@ -0,0 +1,50 @@
|
||||
//=======================================================================
|
||||
// Copyright Baptiste Wicht 2013-2014.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#ifndef TYPE_TRAITS_H
|
||||
#define TYPE_TRAITS_H
|
||||
|
||||
#include "enable_if.hpp"
|
||||
|
||||
namespace std {
|
||||
|
||||
template<typename T>
|
||||
struct is_trivially_destructible {
|
||||
static constexpr const bool value = __has_trivial_destructor(T);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_reference {
|
||||
static constexpr const bool value = false;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_reference<T&>{
|
||||
static constexpr const bool value = true;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_reference<T&&>{
|
||||
static constexpr const bool value = true;
|
||||
};
|
||||
|
||||
template<typename T, typename Enable = void>
|
||||
struct add_rvalue_reference;
|
||||
|
||||
template<typename T>
|
||||
struct add_rvalue_reference<T, typename std::enable_if<std::is_reference<T>::value>::type> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct add_rvalue_reference<T, typename std::enable_if<!std::is_reference<T>::value>::type> {
|
||||
typedef T&& type;
|
||||
};
|
||||
|
||||
} //end of namespace std
|
||||
|
||||
#endif
|
27
tstl/include/utility.hpp
Normal file
27
tstl/include/utility.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
//=======================================================================
|
||||
// Copyright Baptiste Wicht 2013-2014.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#ifndef UTILITY_H
|
||||
#define UTILITY_H
|
||||
|
||||
#include "type_traits.hpp"
|
||||
|
||||
namespace std {
|
||||
|
||||
template <typename T>
|
||||
void swap (T& a, T& b){
|
||||
T c(std::move(a));
|
||||
a = std::move(b);
|
||||
b = std::move(c);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename std::add_rvalue_reference<T>::type declval();
|
||||
|
||||
} //end of namespace std
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user