diff --git a/tstl/include/algorithms.hpp b/tstl/include/algorithms.hpp index 475f4cb8..505309f9 100644 --- a/tstl/include/algorithms.hpp +++ b/tstl/include/algorithms.hpp @@ -26,6 +26,11 @@ constexpr T&& forward(typename remove_reference::type& t ){ return static_cast(t); } +template +constexpr T&& forward(typename remove_reference::type&& t ){ + return static_cast(t); +} + template void copy(OutputIterator out, InputIterator it, InputIterator end){ if(it != end){ diff --git a/tstl/include/conditional.hpp b/tstl/include/conditional.hpp new file mode 100644 index 00000000..5d7fdbb8 --- /dev/null +++ b/tstl/include/conditional.hpp @@ -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 +struct conditional {}; + +template +struct conditional { typedef If type; }; + +template +struct conditional { typedef Else type; }; + +} //end of namespace std + +#endif diff --git a/tstl/include/expected.hpp b/tstl/include/expected.hpp new file mode 100644 index 00000000..6bed1ecd --- /dev/null +++ b/tstl/include/expected.hpp @@ -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 +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 +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& e) : error(e.error){ + //Nothing else to init + } + + template + constexpr trivial_expected_storage(Args&&... args): value(std::forward(args)...){ + //Nothing else to init + } + + ~trivial_expected_storage() = default; +}; + +template +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& e) : error(e.error){ + //Nothing else to init + } + + template + constexpr non_trivial_expected_storage(Args&&... args): value(std::forward(args)...){ + //Nothing else to init + } + + ~non_trivial_expected_storage() {}; +}; + +template +struct trivial_expected_base { + typedef T value_type; + typedef E error_type; + + bool has_value; + trivial_expected_storage 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(v)){ + //Nothing else to init + } + + trivial_expected_base(const exceptional& e) : has_value(false), storage(e) { + //Nothing else to init + } + + ~trivial_expected_base() = default; +}; + +template +struct non_trivial_expected_base { + typedef T value_type; + typedef E error_type; + + bool has_value; + trivial_expected_storage 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(v)){ + //Nothing else to init + } + + non_trivial_expected_base(const exceptional& 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 +using expected_base = typename std::conditional< + std::is_trivially_destructible::value && std::is_trivially_destructible::value, + trivial_expected_base, + non_trivial_expected_base + >::type; + +template +struct expected : expected_base { + typedef T value_type; + typedef E error_type; + + typedef expected this_type; + typedef expected_base 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(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& 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 get_exceptional() const { + return exceptional(contained_error()); + } +}; + +template +inline expected make_expected(T&& v){ + return expected(std::forward(v)); +} + +template +inline expected make_expected_from_error(E v){ + return expected(exceptional(v)); +} + +template +inline expected make_expected_from_error(E v){ + return expected(exceptional(v)); +} + +} //end of namespace std + +#endif diff --git a/tstl/include/memory.hpp b/tstl/include/memory.hpp new file mode 100644 index 00000000..e591df9a --- /dev/null +++ b/tstl/include/memory.hpp @@ -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( + &const_cast( + reinterpret_cast(arg))); +} + +template +struct has_overloaded_addressof { + template + static constexpr bool has_overload(...) { + return false; + } + + template ().operator&()) > + static constexpr bool has_overload(bool) { + return true; + } + + constexpr static bool value = has_overload(true); +}; + +template +constexpr typename std::disable_if::value, T*>::type +static_addressof(T& ref){ + return &ref; +} + +template +constexpr typename std::enable_if::value, T*>::type +static_addressof(T& ref){ + return std::addressof(ref); +} + +} //end of namespace std + +#endif diff --git a/tstl/include/new.hpp b/tstl/include/new.hpp new file mode 100644 index 00000000..a55ddae7 --- /dev/null +++ b/tstl/include/new.hpp @@ -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 diff --git a/tstl/include/type_traits.hpp b/tstl/include/type_traits.hpp new file mode 100644 index 00000000..2f0d6b83 --- /dev/null +++ b/tstl/include/type_traits.hpp @@ -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 +struct is_trivially_destructible { + static constexpr const bool value = __has_trivial_destructor(T); +}; + +template +struct is_reference { + static constexpr const bool value = false; +}; + +template +struct is_reference{ + static constexpr const bool value = true; +}; + +template +struct is_reference{ + static constexpr const bool value = true; +}; + +template +struct add_rvalue_reference; + +template +struct add_rvalue_reference::value>::type> { + typedef T type; +}; + +template +struct add_rvalue_reference::value>::type> { + typedef T&& type; +}; + +} //end of namespace std + +#endif diff --git a/tstl/include/utility.hpp b/tstl/include/utility.hpp new file mode 100644 index 00000000..a5ebe276 --- /dev/null +++ b/tstl/include/utility.hpp @@ -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 +void swap (T& a, T& b){ + T c(std::move(a)); + a = std::move(b); + b = std::move(c); +} + +template +typename std::add_rvalue_reference::type declval(); + +} //end of namespace std + +#endif