Prototype of std::expected

This commit is contained in:
Baptiste Wicht 2014-02-09 16:22:23 +01:00
parent cf43087848
commit ac602e40ed
7 changed files with 532 additions and 0 deletions

View File

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

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

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