#define TL_EXPECTED_HPP
#define TL_EXPECTED_VERSION_MAJOR 1
-#define TL_EXPECTED_VERSION_MINOR 1
+#define TL_EXPECTED_VERSION_MINOR 2
#define TL_EXPECTED_VERSION_PATCH 0
#include <exception>
#if !defined(TL_ASSERT)
//can't have assert in constexpr in C++11 and GCC 4.9 has a compiler bug
-#if (__cplusplus > 201103L) && !defined(TL_EXPECTED_GCC49)
+#if (TL_CPLUSPLUS > 201103L) && !defined(TL_EXPECTED_GCC49)
#include <cassert>
#define TL_ASSERT(x) assert(x)
#else
std::is_trivially_destructible<T>
#endif
-#if __cplusplus > 201103L
+#ifdef _MSVC_LANG
+#define TL_CPLUSPLUS _MSVC_LANG
+#else
+#define TL_CPLUSPLUS __cplusplus
+#endif
+
+#if TL_CPLUSPLUS > 201103L
#define TL_EXPECTED_CXX14
#endif
#define TL_EXPECTED_GCC49_CONSTEXPR constexpr
#endif
-#if (__cplusplus == 201103L || defined(TL_EXPECTED_MSVC2015) || \
+#if (TL_CPLUSPLUS == 201103L || defined(TL_EXPECTED_MSVC2015) || \
defined(TL_EXPECTED_GCC49))
#define TL_EXPECTED_11_CONSTEXPR
#else
#define TL_EXPECTED_11_CONSTEXPR constexpr
#endif
+#if TL_CPLUSPLUS >= 201703L
+#define TL_EXPECTED_NODISCARD [[nodiscard]]
+#else
+#define TL_EXPECTED_NODISCARD
+#endif
+
namespace tl {
-template <class T, class E> class expected;
+template <class T, class E> class TL_EXPECTED_NODISCARD expected;
#ifndef TL_MONOSTATE_INPLACE_MUTEX
#define TL_MONOSTATE_INPLACE_MUTEX
Args &&...args)
: m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
+ expected_storage_base(const expected_storage_base &) = default;
+ expected_storage_base(expected_storage_base &&) = default;
+ expected_storage_base &operator=(const expected_storage_base &) = default;
+ expected_storage_base &operator=(expected_storage_base &&) = default;
~expected_storage_base() = default;
union {
T m_val;
Args &&...args)
: m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
+ expected_storage_base(const expected_storage_base &) = default;
+ expected_storage_base(expected_storage_base &&) = default;
+ expected_storage_base &operator=(const expected_storage_base &) = default;
+ expected_storage_base &operator=(expected_storage_base &&) = default;
~expected_storage_base() {
if (!m_has_val) {
m_unexpect.~unexpected<E>();
Args &&...args)
: m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
+ expected_storage_base(const expected_storage_base &) = default;
+ expected_storage_base(expected_storage_base &&) = default;
+ expected_storage_base &operator=(const expected_storage_base &) = default;
+ expected_storage_base &operator=(expected_storage_base &&) = default;
~expected_storage_base() {
if (m_has_val) {
m_val.~T();
Args &&...args)
: m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
+ expected_storage_base(const expected_storage_base &) = default;
+ expected_storage_base(expected_storage_base &&) = default;
+ expected_storage_base &operator=(const expected_storage_base &) = default;
+ expected_storage_base &operator=(expected_storage_base &&) = default;
~expected_storage_base() = default;
struct dummy {};
union {
Args &&...args)
: m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
+ expected_storage_base(const expected_storage_base &) = default;
+ expected_storage_base(expected_storage_base &&) = default;
+ expected_storage_base &operator=(const expected_storage_base &) = default;
+ expected_storage_base &operator=(expected_storage_base &&) = default;
~expected_storage_base() {
if (!m_has_val) {
m_unexpect.~unexpected<E>();
// This specialization is for when T and E are trivially copy constructible
template <class T, class E,
bool = is_void_or<T, TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>::
- value &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value>
+ value &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value,
+ bool = (is_copy_constructible_or_void<T>::value &&
+ std::is_copy_constructible<E>::value)>
struct expected_copy_base : expected_operations_base<T, E> {
using expected_operations_base<T, E>::expected_operations_base;
};
-// This specialization is for when T or E are not trivially copy constructible
+// This specialization is for when T or E are non-trivially copy constructible
template <class T, class E>
-struct expected_copy_base<T, E, false> : expected_operations_base<T, E> {
+struct expected_copy_base<T, E, false, true> : expected_operations_base<T, E> {
using expected_operations_base<T, E>::expected_operations_base;
expected_copy_base() = default;
TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)>>::value
&&TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value
&&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value
- &&TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value>
+ &&TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value,
+ bool = (is_copy_constructible_or_void<T>::value &&
+ std::is_copy_constructible<E>::value &&
+ is_copy_assignable_or_void<T>::value &&
+ std::is_copy_assignable<E>::value)>
struct expected_copy_assign_base : expected_move_base<T, E> {
using expected_move_base<T, E>::expected_move_base;
};
template <class T, class E>
-struct expected_copy_assign_base<T, E, false> : expected_move_base<T, E> {
+struct expected_copy_assign_base<T, E, false, true> : expected_move_base<T, E> {
using expected_move_base<T, E>::expected_move_base;
expected_copy_assign_base() = default;
};
// expected_default_ctor_base will ensure that expected has a deleted default
-// consturctor if T is not default constructible.
+// constructor if T is not default constructible.
// This specialization is for when T is default constructible
template <class T, class E,
bool Enable =
/// has been destroyed. The initialization state of the contained object is
/// tracked by the expected object.
template <class T, class E>
-class expected : private detail::expected_move_assign_base<T, E>,
+class TL_EXPECTED_NODISCARD expected :
+ private detail::expected_move_assign_base<T, E>,
private detail::expected_delete_ctor_base<T, E>,
private detail::expected_delete_assign_base<T, E>,
private detail::expected_default_ctor_base<T, E> {
const expected<void, F> &rhs) {
return (lhs.has_value() != rhs.has_value())
? true
- : (!lhs.has_value() ? lhs.error() == rhs.error() : false);
+ : (!lhs.has_value() ? lhs.error() != rhs.error() : false);
}
template <class T, class E, class U>