forked from TartanLlama/expected
Rename map_impl
This commit is contained in:
311
tl/expected.hpp
311
tl/expected.hpp
@@ -50,23 +50,26 @@
|
|||||||
|
|
||||||
// GCC < 5 doesn't support some standard C++11 type traits
|
// GCC < 5 doesn't support some standard C++11 type traits
|
||||||
/// \exclude
|
/// \exclude
|
||||||
#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
|
#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
|
||||||
std::has_trivial_copy_constructor<T>
|
std::has_trivial_copy_constructor<T>
|
||||||
/// \exclude
|
/// \exclude
|
||||||
#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>
|
#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
|
||||||
|
std::has_trivial_copy_assign<T>
|
||||||
|
|
||||||
// This one will be different for GCC 5.7 if it's ever supported
|
// This one will be different for GCC 5.7 if it's ever supported
|
||||||
/// \exclude
|
/// \exclude
|
||||||
#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>
|
#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
|
||||||
|
std::is_trivially_destructible<T>
|
||||||
#else
|
#else
|
||||||
/// \exclude
|
/// \exclude
|
||||||
#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
|
#define TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
|
||||||
std::is_trivially_copy_constructible<T>
|
std::is_trivially_copy_constructible<T>
|
||||||
/// \exclude
|
/// \exclude
|
||||||
#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
|
#define TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
|
||||||
std::is_trivially_copy_assignable<T>
|
std::is_trivially_copy_assignable<T>
|
||||||
/// \exclude
|
/// \exclude
|
||||||
#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>
|
#define TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
|
||||||
|
std::is_trivially_destructible<T>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __cplusplus > 201103L
|
#if __cplusplus > 201103L
|
||||||
@@ -262,15 +265,16 @@ using expected_enable_from_other = detail::enable_if_t<
|
|||||||
!std::is_convertible<const expected<U, G> &, T>::value &&
|
!std::is_convertible<const expected<U, G> &, T>::value &&
|
||||||
!std::is_convertible<const expected<U, G> &&, T>::value>;
|
!std::is_convertible<const expected<U, G> &&, T>::value>;
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
using is_void_or = conditional_t<std::is_void<T>::value, std::true_type, U>;
|
using is_void_or = conditional_t<std::is_void<T>::value, std::true_type, U>;
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
using is_copy_constructible_or_void = is_void_or<T,std::is_copy_constructible<T>>;
|
using is_copy_constructible_or_void =
|
||||||
|
is_void_or<T, std::is_copy_constructible<T>>;
|
||||||
template <class T>
|
|
||||||
using is_move_constructible_or_void = is_void_or<T,std::is_move_constructible<T>>;
|
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
using is_move_constructible_or_void =
|
||||||
|
is_void_or<T, std::is_move_constructible<T>>;
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
@@ -374,7 +378,8 @@ template <class T, class E> struct expected_storage_base<T, E, true, true> {
|
|||||||
// T is trivial, E is not.
|
// T is trivial, E is not.
|
||||||
template <class T, class E> struct expected_storage_base<T, E, true, false> {
|
template <class T, class E> struct expected_storage_base<T, E, true, false> {
|
||||||
constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
|
constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
|
||||||
TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base(no_init_t) : m_has_val(false) {}
|
TL_EXPECTED_MSVC2015_CONSTEXPR expected_storage_base(no_init_t)
|
||||||
|
: m_has_val(false) {}
|
||||||
|
|
||||||
template <class... Args,
|
template <class... Args,
|
||||||
detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
|
detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
|
||||||
@@ -529,16 +534,15 @@ template <class T, class E>
|
|||||||
struct expected_operations_base : expected_storage_base<T, E> {
|
struct expected_operations_base : expected_storage_base<T, E> {
|
||||||
using expected_storage_base<T, E>::expected_storage_base;
|
using expected_storage_base<T, E>::expected_storage_base;
|
||||||
|
|
||||||
template <class... Args> void construct(Args &&... args) noexcept {
|
template <class... Args> void construct(Args &&... args) noexcept {
|
||||||
new (std::addressof(this->m_val)) T(std::forward<Args>(args)...);
|
new (std::addressof(this->m_val)) T(std::forward<Args>(args)...);
|
||||||
this->m_has_val = true;
|
this->m_has_val = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Rhs>
|
template <class Rhs> void construct_with(Rhs &&rhs) noexcept {
|
||||||
void construct_with(Rhs && rhs) noexcept {
|
new (std::addressof(this->m_val)) T(std::forward<Rhs>(rhs).get());
|
||||||
new (std::addressof(this->m_val)) T(std::forward<Rhs>(rhs).get());
|
this->m_has_val = true;
|
||||||
this->m_has_val = true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Args> void construct_error(Args &&... args) noexcept {
|
template <class... Args> void construct_error(Args &&... args) noexcept {
|
||||||
new (std::addressof(this->m_unexpect))
|
new (std::addressof(this->m_unexpect))
|
||||||
@@ -678,18 +682,15 @@ struct expected_operations_base : expected_storage_base<T, E> {
|
|||||||
// This base class provides some handy member functions which can be used in
|
// This base class provides some handy member functions which can be used in
|
||||||
// further derived classes
|
// further derived classes
|
||||||
template <class E>
|
template <class E>
|
||||||
struct expected_operations_base<void,E> : expected_storage_base<void, E> {
|
struct expected_operations_base<void, E> : expected_storage_base<void, E> {
|
||||||
using expected_storage_base<void, E>::expected_storage_base;
|
using expected_storage_base<void, E>::expected_storage_base;
|
||||||
|
|
||||||
template <class... Args> void construct() noexcept {
|
template <class... Args> void construct() noexcept { this->m_has_val = true; }
|
||||||
this->m_has_val = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function doesn't use its argument, but needs it so that code in
|
// This function doesn't use its argument, but needs it so that code in
|
||||||
// levels above this can work independently of whether T is void
|
// levels above this can work independently of whether T is void
|
||||||
template <class Rhs>
|
template <class Rhs> void construct_with(Rhs &&) noexcept {
|
||||||
void construct_with(Rhs &&) noexcept {
|
this->m_has_val = true;
|
||||||
this->m_has_val = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class... Args> void construct_error(Args &&... args) noexcept {
|
template <class... Args> void construct_error(Args &&... args) noexcept {
|
||||||
@@ -698,20 +699,18 @@ struct expected_operations_base<void,E> : expected_storage_base<void, E> {
|
|||||||
this->m_has_val = false;
|
this->m_has_val = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Rhs>
|
template <class Rhs> void assign(Rhs &&rhs) noexcept {
|
||||||
void assign(Rhs &&rhs) noexcept {
|
|
||||||
if (!this->m_has_val) {
|
if (!this->m_has_val) {
|
||||||
if (rhs.m_has_val) {
|
if (rhs.m_has_val) {
|
||||||
geterr().~unexpected<E>();
|
geterr().~unexpected<E>();
|
||||||
construct();
|
construct();
|
||||||
}
|
} else {
|
||||||
else {
|
geterr() = std::forward<Rhs>(rhs).geterr();
|
||||||
geterr() = std::forward<Rhs>(rhs).geterr();
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!rhs.m_has_val) {
|
if (!rhs.m_has_val) {
|
||||||
construct_error(std::forward<Rhs>(rhs).geterr());
|
construct_error(std::forward<Rhs>(rhs).geterr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,8 +733,8 @@ struct expected_operations_base<void,E> : expected_storage_base<void, E> {
|
|||||||
// This class manages conditionally having a trivial copy constructor
|
// This class manages conditionally having a trivial copy constructor
|
||||||
// This specialization is for when T and E are trivially copy constructible
|
// This specialization is for when T and E are trivially copy constructible
|
||||||
template <class T, class E,
|
template <class T, class E,
|
||||||
bool = is_void_or<T,TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>::value &&
|
bool = is_void_or<T, TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>::
|
||||||
TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value>
|
value &&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value>
|
||||||
struct expected_copy_base : expected_operations_base<T, E> {
|
struct expected_copy_base : expected_operations_base<T, E> {
|
||||||
using expected_operations_base<T, E>::expected_operations_base;
|
using expected_operations_base<T, E>::expected_operations_base;
|
||||||
};
|
};
|
||||||
@@ -767,7 +766,7 @@ struct expected_copy_base<T, E, false> : expected_operations_base<T, E> {
|
|||||||
// move constructible
|
// move constructible
|
||||||
#ifndef TL_EXPECTED_GCC49
|
#ifndef TL_EXPECTED_GCC49
|
||||||
template <class T, class E,
|
template <class T, class E,
|
||||||
bool = is_void_or<T,std::is_trivially_move_constructible<T>>::value
|
bool = is_void_or<T, std::is_trivially_move_constructible<T>>::value
|
||||||
&&std::is_trivially_move_constructible<E>::value>
|
&&std::is_trivially_move_constructible<E>::value>
|
||||||
struct expected_move_base : expected_copy_base<T, E> {
|
struct expected_move_base : expected_copy_base<T, E> {
|
||||||
using expected_copy_base<T, E>::expected_copy_base;
|
using expected_copy_base<T, E>::expected_copy_base;
|
||||||
@@ -796,14 +795,14 @@ struct expected_move_base<T, E, false> : expected_copy_base<T, E> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// This class manages conditionally having a trivial copy assignment operator
|
// This class manages conditionally having a trivial copy assignment operator
|
||||||
template <
|
template <class T, class E,
|
||||||
class T, class E,
|
bool = is_void_or<
|
||||||
bool = is_void_or<T,
|
T, conjunction<TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T),
|
||||||
conjunction<TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T),
|
TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T),
|
||||||
TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T),
|
TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)>>::value
|
||||||
TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)>>::value &&
|
&&TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value
|
||||||
TL_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value &&
|
&&TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value
|
||||||
TL_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value && TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value>
|
&&TL_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value>
|
||||||
struct expected_copy_assign_base : expected_move_base<T, E> {
|
struct expected_copy_assign_base : expected_move_base<T, E> {
|
||||||
using expected_move_base<T, E>::expected_move_base;
|
using expected_move_base<T, E>::expected_move_base;
|
||||||
};
|
};
|
||||||
@@ -832,12 +831,12 @@ struct expected_copy_assign_base<T, E, false> : expected_move_base<T, E> {
|
|||||||
#ifndef TL_EXPECTED_GCC49
|
#ifndef TL_EXPECTED_GCC49
|
||||||
template <class T, class E,
|
template <class T, class E,
|
||||||
bool =
|
bool =
|
||||||
is_void_or<T, conjunction<std::is_trivially_destructible<T>,
|
is_void_or<T, conjunction<std::is_trivially_destructible<T>,
|
||||||
std::is_trivially_move_constructible<T>,
|
std::is_trivially_move_constructible<T>,
|
||||||
std::is_trivially_move_assignable<T>>>::value
|
std::is_trivially_move_assignable<T>>>::
|
||||||
&&std::is_trivially_destructible<E>::value
|
value &&std::is_trivially_destructible<E>::value
|
||||||
&&std::is_trivially_move_constructible<E>::value
|
&&std::is_trivially_move_constructible<E>::value
|
||||||
&&std::is_trivially_move_assignable<E>::value>
|
&&std::is_trivially_move_assignable<E>::value>
|
||||||
struct expected_move_assign_base : expected_copy_assign_base<T, E> {
|
struct expected_move_assign_base : expected_copy_assign_base<T, E> {
|
||||||
using expected_copy_assign_base<T, E>::expected_copy_assign_base;
|
using expected_copy_assign_base<T, E>::expected_copy_assign_base;
|
||||||
};
|
};
|
||||||
@@ -986,7 +985,8 @@ struct default_constructor_tag {
|
|||||||
// consturctor if T is not default constructible.
|
// consturctor if T is not default constructible.
|
||||||
// This specialization is for when T is default constructible
|
// This specialization is for when T is default constructible
|
||||||
template <class T, class E,
|
template <class T, class E,
|
||||||
bool Enable = std::is_default_constructible<T>::value || std::is_void<T>::value>
|
bool Enable =
|
||||||
|
std::is_default_constructible<T>::value || std::is_void<T>::value>
|
||||||
struct expected_default_ctor_base {
|
struct expected_default_ctor_base {
|
||||||
constexpr expected_default_ctor_base() noexcept = default;
|
constexpr expected_default_ctor_base() noexcept = default;
|
||||||
constexpr expected_default_ctor_base(
|
constexpr expected_default_ctor_base(
|
||||||
@@ -1058,12 +1058,18 @@ class expected : private detail::expected_move_assign_base<T, E>,
|
|||||||
T *valptr() { return std::addressof(this->m_val); }
|
T *valptr() { return std::addressof(this->m_val); }
|
||||||
unexpected<E> *errptr() { return std::addressof(this->m_unexpect); }
|
unexpected<E> *errptr() { return std::addressof(this->m_unexpect); }
|
||||||
|
|
||||||
template <class U=T, detail::enable_if_t<!std::is_void<U>::value>* = nullptr>
|
template <class U = T,
|
||||||
U &val() { return this->m_val; }
|
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
|
||||||
|
U &val() {
|
||||||
|
return this->m_val;
|
||||||
|
}
|
||||||
unexpected<E> &err() { return this->m_unexpect; }
|
unexpected<E> &err() { return this->m_unexpect; }
|
||||||
|
|
||||||
template <class U=T, detail::enable_if_t<!std::is_void<U>::value>* = nullptr>
|
template <class U = T,
|
||||||
const U &val() const { return this->m_val; }
|
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
|
||||||
|
const U &val() const {
|
||||||
|
return this->m_val;
|
||||||
|
}
|
||||||
const unexpected<E> &err() const { return this->m_unexpect; }
|
const unexpected<E> &err() const { return this->m_unexpect; }
|
||||||
|
|
||||||
using impl_base = detail::expected_move_assign_base<T, E>;
|
using impl_base = detail::expected_move_assign_base<T, E>;
|
||||||
@@ -1086,26 +1092,26 @@ public:
|
|||||||
/// is returned.
|
/// is returned.
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
|
||||||
template <class F> TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & {
|
template <class F> TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & {
|
||||||
return and_then_impl(*this, std::forward<F>(f));
|
return and_then_impl(*this, std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \group and_then
|
/// \group and_then
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
|
||||||
template <class F> TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && {
|
template <class F> TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && {
|
||||||
return and_then_impl(std::move(*this), std::forward<F>(f));
|
return and_then_impl(std::move(*this), std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \group and_then
|
/// \group and_then
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
|
||||||
template <class F> constexpr auto and_then(F &&f) const & {
|
template <class F> constexpr auto and_then(F &&f) const & {
|
||||||
return and_then_impl(*this, std::forward<F>(f));
|
return and_then_impl(*this, std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TL_EXPECTED_NO_CONSTRR
|
#ifndef TL_EXPECTED_NO_CONSTRR
|
||||||
/// \group and_then
|
/// \group and_then
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
|
||||||
template <class F> constexpr auto and_then(F &&f) const && {
|
template <class F> constexpr auto and_then(F &&f) const && {
|
||||||
return and_then_impl(std::move(*this), std::forward<F>(f));
|
return and_then_impl(std::move(*this), std::forward<F>(f));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1120,30 +1126,34 @@ public:
|
|||||||
/// is returned.
|
/// is returned.
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
|
||||||
template <class F>
|
template <class F>
|
||||||
TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) & -> decltype(and_then_impl(*this, std::forward<F>(f))) {
|
TL_EXPECTED_11_CONSTEXPR auto
|
||||||
return and_then_impl(*this, std::forward<F>(f));
|
and_then(F &&f) & -> decltype(and_then_impl(*this, std::forward<F>(f))) {
|
||||||
|
return and_then_impl(*this, std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \group and_then
|
/// \group and_then
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
|
||||||
template <class F>
|
template <class F>
|
||||||
TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && -> decltype(and_then_impl(std::move(*this), std::forward<F>(f))) {
|
TL_EXPECTED_11_CONSTEXPR auto and_then(F &&f) && -> decltype(
|
||||||
return and_then_impl(std::move(*this), std::forward<F>(f));
|
and_then_impl(std::move(*this), std::forward<F>(f))) {
|
||||||
|
return and_then_impl(std::move(*this), std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \group and_then
|
/// \group and_then
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
|
||||||
template <class F>
|
template <class F>
|
||||||
constexpr auto and_then(F &&f) const & -> decltype(and_then_impl(*this, std::forward<F>(f))) {
|
constexpr auto and_then(F &&f) const & -> decltype(
|
||||||
return and_then_impl(*this, std::forward<F>(f));
|
and_then_impl(*this, std::forward<F>(f))) {
|
||||||
|
return and_then_impl(*this, std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TL_EXPECTED_NO_CONSTRR
|
#ifndef TL_EXPECTED_NO_CONSTRR
|
||||||
/// \group and_then
|
/// \group and_then
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
|
||||||
template <class F>
|
template <class F>
|
||||||
constexpr auto and_then(F &&f) const && -> decltype(and_then_impl(std::move(*this), std::forward<F>(f))) {
|
constexpr auto and_then(F &&f) const && -> decltype(
|
||||||
return and_then_impl(std::move(*this), std::forward<F>(f));
|
and_then_impl(std::move(*this), std::forward<F>(f))) {
|
||||||
|
return and_then_impl(std::move(*this), std::forward<F>(f));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@@ -1161,25 +1171,25 @@ public:
|
|||||||
/// \group map
|
/// \group map
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) &;
|
/// \synopsis template <class F> constexpr auto map(F &&f) &;
|
||||||
template <class F> TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & {
|
template <class F> TL_EXPECTED_11_CONSTEXPR auto map(F &&f) & {
|
||||||
return map_impl(*this, std::forward<F>(f));
|
return expected_map_impl(*this, std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \group map
|
/// \group map
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) &&;
|
/// \synopsis template <class F> constexpr auto map(F &&f) &&;
|
||||||
template <class F> TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && {
|
template <class F> TL_EXPECTED_11_CONSTEXPR auto map(F &&f) && {
|
||||||
return map_impl(std::move(*this), std::forward<F>(f));
|
return expected_map_impl(std::move(*this), std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \group map
|
/// \group map
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) const &;
|
/// \synopsis template <class F> constexpr auto map(F &&f) const &;
|
||||||
template <class F> constexpr auto map(F &&f) const & {
|
template <class F> constexpr auto map(F &&f) const & {
|
||||||
return map_impl(*this, std::forward<F>(f));
|
return expected_map_impl(*this, std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \group map
|
/// \group map
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) const &&;
|
/// \synopsis template <class F> constexpr auto map(F &&f) const &&;
|
||||||
template <class F> constexpr auto map(F &&f) const && {
|
template <class F> constexpr auto map(F &&f) const && {
|
||||||
return map_impl(std::move(*this), std::forward<F>(f));
|
return expected_map_impl(std::move(*this), std::forward<F>(f));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/// \brief Carries out some operation on the stored object if there is one.
|
/// \brief Carries out some operation on the stored object if there is one.
|
||||||
@@ -1193,38 +1203,38 @@ public:
|
|||||||
/// \group map
|
/// \group map
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) &;
|
/// \synopsis template <class F> constexpr auto map(F &&f) &;
|
||||||
template <class F>
|
template <class F>
|
||||||
TL_EXPECTED_11_CONSTEXPR decltype(map_impl(std::declval<expected &>(),
|
TL_EXPECTED_11_CONSTEXPR decltype(
|
||||||
std::declval<F &&>()))
|
expected_map_impl(std::declval<expected &>(), std::declval<F &&>()))
|
||||||
map(F &&f) & {
|
map(F &&f) & {
|
||||||
return map_impl(*this, std::forward<F>(f));
|
return expected_map_impl(*this, std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \group map
|
/// \group map
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) &&;
|
/// \synopsis template <class F> constexpr auto map(F &&f) &&;
|
||||||
template <class F>
|
template <class F>
|
||||||
TL_EXPECTED_11_CONSTEXPR decltype(map_impl(std::declval<expected &>(),
|
TL_EXPECTED_11_CONSTEXPR decltype(
|
||||||
std::declval<F &&>()))
|
expected_map_impl(std::declval<expected &>(), std::declval<F &&>()))
|
||||||
map(F &&f) && {
|
map(F &&f) && {
|
||||||
return map_impl(std::move(*this), std::forward<F>(f));
|
return expected_map_impl(std::move(*this), std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \group map
|
/// \group map
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) const &;
|
/// \synopsis template <class F> constexpr auto map(F &&f) const &;
|
||||||
template <class F>
|
template <class F>
|
||||||
constexpr decltype(map_impl(std::declval<const expected &>(),
|
constexpr decltype(expected_map_impl(std::declval<const expected &>(),
|
||||||
std::declval<F &&>()))
|
std::declval<F &&>()))
|
||||||
map(F &&f) const & {
|
map(F &&f) const & {
|
||||||
return map_impl(*this, std::forward<F>(f));
|
return expected_map_impl(*this, std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TL_EXPECTED_NO_CONSTRR
|
#ifndef TL_EXPECTED_NO_CONSTRR
|
||||||
/// \group map
|
/// \group map
|
||||||
/// \synopsis template <class F> constexpr auto map(F &&f) const &&;
|
/// \synopsis template <class F> constexpr auto map(F &&f) const &&;
|
||||||
template <class F>
|
template <class F>
|
||||||
constexpr decltype(map_impl(std::declval<const expected &&>(),
|
constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
|
||||||
std::declval<F &&>()))
|
std::declval<F &&>()))
|
||||||
map(F &&f) const && {
|
map(F &&f) const && {
|
||||||
return map_impl(std::move(*this), std::forward<F>(f));
|
return expected_map_impl(std::move(*this), std::forward<F>(f));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@@ -1477,29 +1487,29 @@ public:
|
|||||||
class U = T,
|
class U = T,
|
||||||
detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr,
|
detail::enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr,
|
||||||
detail::expected_enable_forward_value<T, E, U> * = nullptr>
|
detail::expected_enable_forward_value<T, E, U> * = nullptr>
|
||||||
explicit TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) : expected(in_place, std::forward<U>(v)) {}
|
explicit TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v)
|
||||||
|
: expected(in_place, std::forward<U>(v)) {}
|
||||||
|
|
||||||
/// \exclude
|
/// \exclude
|
||||||
template <
|
template <
|
||||||
class U = T,
|
class U = T,
|
||||||
detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr,
|
detail::enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr,
|
||||||
detail::expected_enable_forward_value<T, E, U> * = nullptr>
|
detail::expected_enable_forward_value<T, E, U> * = nullptr>
|
||||||
TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v) : expected(in_place, std::forward<U>(v)) {}
|
TL_EXPECTED_MSVC2015_CONSTEXPR expected(U &&v)
|
||||||
|
: expected(in_place, std::forward<U>(v)) {}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
class U = T,
|
class U = T, class G = T,
|
||||||
class G = T,
|
|
||||||
detail::enable_if_t<std::is_nothrow_constructible<T, U &&>::value> * =
|
detail::enable_if_t<std::is_nothrow_constructible<T, U &&>::value> * =
|
||||||
nullptr,
|
nullptr,
|
||||||
detail::enable_if_t<!std::is_void<G>::value>* = nullptr,
|
detail::enable_if_t<!std::is_void<G>::value> * = nullptr,
|
||||||
detail::enable_if_t<
|
detail::enable_if_t<
|
||||||
(!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
|
(!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
|
||||||
!detail::conjunction<std::is_scalar<T>,
|
!detail::conjunction<std::is_scalar<T>,
|
||||||
std::is_same<T, detail::decay_t<U>>>::value &&
|
std::is_same<T, detail::decay_t<U>>>::value &&
|
||||||
std::is_constructible<T, U>::value &&
|
std::is_constructible<T, U>::value &&
|
||||||
std::is_assignable<G &, U>::value &&
|
std::is_assignable<G &, U>::value &&
|
||||||
std::is_nothrow_move_constructible<E>::value)> * = nullptr
|
std::is_nothrow_move_constructible<E>::value)> * = nullptr>
|
||||||
>
|
|
||||||
expected &operator=(U &&v) {
|
expected &operator=(U &&v) {
|
||||||
if (has_value()) {
|
if (has_value()) {
|
||||||
val() = std::forward<U>(v);
|
val() = std::forward<U>(v);
|
||||||
@@ -1514,19 +1524,17 @@ public:
|
|||||||
|
|
||||||
/// \exclude
|
/// \exclude
|
||||||
template <
|
template <
|
||||||
class U = T,
|
class U = T, class G = T,
|
||||||
class G = T,
|
|
||||||
detail::enable_if_t<!std::is_nothrow_constructible<T, U &&>::value> * =
|
detail::enable_if_t<!std::is_nothrow_constructible<T, U &&>::value> * =
|
||||||
nullptr,
|
nullptr,
|
||||||
detail::enable_if_t<!std::is_void<U>::value>* = nullptr,
|
detail::enable_if_t<!std::is_void<U>::value> * = nullptr,
|
||||||
detail::enable_if_t<
|
detail::enable_if_t<
|
||||||
(!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
|
(!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
|
||||||
!detail::conjunction<std::is_scalar<T>,
|
!detail::conjunction<std::is_scalar<T>,
|
||||||
std::is_same<T, detail::decay_t<U>>>::value &&
|
std::is_same<T, detail::decay_t<U>>>::value &&
|
||||||
std::is_constructible<T, U>::value &&
|
std::is_constructible<T, U>::value &&
|
||||||
std::is_assignable<G &, U>::value &&
|
std::is_assignable<G &, U>::value &&
|
||||||
std::is_nothrow_move_constructible<E>::value)> * = nullptr
|
std::is_nothrow_move_constructible<E>::value)> * = nullptr>
|
||||||
>
|
|
||||||
expected &operator=(U &&v) {
|
expected &operator=(U &&v) {
|
||||||
if (has_value()) {
|
if (has_value()) {
|
||||||
val() = std::forward<U>(v);
|
val() = std::forward<U>(v);
|
||||||
@@ -1678,17 +1686,29 @@ public:
|
|||||||
/// \returns the stored value
|
/// \returns the stored value
|
||||||
/// \requires a value is stored
|
/// \requires a value is stored
|
||||||
/// \group deref
|
/// \group deref
|
||||||
template <class U=T, detail::enable_if_t<!std::is_void<U>::value>* = nullptr>
|
template <class U = T,
|
||||||
constexpr const U &operator*() const & { return val(); }
|
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
|
||||||
|
constexpr const U &operator*() const & {
|
||||||
|
return val();
|
||||||
|
}
|
||||||
/// \group deref
|
/// \group deref
|
||||||
template <class U=T, detail::enable_if_t<!std::is_void<U>::value>* = nullptr>
|
template <class U = T,
|
||||||
TL_EXPECTED_11_CONSTEXPR U &operator*() & { return val(); }
|
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
|
||||||
|
TL_EXPECTED_11_CONSTEXPR U &operator*() & {
|
||||||
|
return val();
|
||||||
|
}
|
||||||
/// \group deref
|
/// \group deref
|
||||||
template <class U=T, detail::enable_if_t<!std::is_void<U>::value>* = nullptr>
|
template <class U = T,
|
||||||
constexpr const U &&operator*() const && { return std::move(val()); }
|
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
|
||||||
|
constexpr const U &&operator*() const && {
|
||||||
|
return std::move(val());
|
||||||
|
}
|
||||||
/// \group deref
|
/// \group deref
|
||||||
template <class U=T, detail::enable_if_t<!std::is_void<U>::value>* = nullptr>
|
template <class U = T,
|
||||||
TL_EXPECTED_11_CONSTEXPR U &&operator*() && { return std::move(val()); }
|
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
|
||||||
|
TL_EXPECTED_11_CONSTEXPR U &&operator*() && {
|
||||||
|
return std::move(val());
|
||||||
|
}
|
||||||
|
|
||||||
/// \returns whether or not the optional has a value
|
/// \returns whether or not the optional has a value
|
||||||
/// \group has_value
|
/// \group has_value
|
||||||
@@ -1700,28 +1720,32 @@ public:
|
|||||||
/// [bad_expected_access]
|
/// [bad_expected_access]
|
||||||
///
|
///
|
||||||
/// \group value
|
/// \group value
|
||||||
template <class U=T, detail::enable_if_t<!std::is_void<U>::value>* = nullptr>
|
template <class U = T,
|
||||||
|
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
|
||||||
TL_EXPECTED_11_CONSTEXPR const U &value() const & {
|
TL_EXPECTED_11_CONSTEXPR const U &value() const & {
|
||||||
if (!has_value())
|
if (!has_value())
|
||||||
throw bad_expected_access<E>(err().value());
|
throw bad_expected_access<E>(err().value());
|
||||||
return val();
|
return val();
|
||||||
}
|
}
|
||||||
/// \group value
|
/// \group value
|
||||||
template <class U=T, detail::enable_if_t<!std::is_void<U>::value>* = nullptr>
|
template <class U = T,
|
||||||
|
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
|
||||||
TL_EXPECTED_11_CONSTEXPR U &value() & {
|
TL_EXPECTED_11_CONSTEXPR U &value() & {
|
||||||
if (!has_value())
|
if (!has_value())
|
||||||
throw bad_expected_access<E>(err().value());
|
throw bad_expected_access<E>(err().value());
|
||||||
return val();
|
return val();
|
||||||
}
|
}
|
||||||
/// \group value
|
/// \group value
|
||||||
template <class U=T, detail::enable_if_t<!std::is_void<U>::value>* = nullptr>
|
template <class U = T,
|
||||||
|
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
|
||||||
TL_EXPECTED_11_CONSTEXPR const U &&value() const && {
|
TL_EXPECTED_11_CONSTEXPR const U &&value() const && {
|
||||||
if (!has_value())
|
if (!has_value())
|
||||||
throw bad_expected_access<E>(err().value());
|
throw bad_expected_access<E>(err().value());
|
||||||
return std::move(val());
|
return std::move(val());
|
||||||
}
|
}
|
||||||
/// \group value
|
/// \group value
|
||||||
template <class U=T, detail::enable_if_t<!std::is_void<U>::value>* = nullptr>
|
template <class U = T,
|
||||||
|
detail::enable_if_t<!std::is_void<U>::value> * = nullptr>
|
||||||
TL_EXPECTED_11_CONSTEXPR U &&value() && {
|
TL_EXPECTED_11_CONSTEXPR U &&value() && {
|
||||||
if (!has_value())
|
if (!has_value())
|
||||||
throw bad_expected_access<E>(err().value());
|
throw bad_expected_access<E>(err().value());
|
||||||
@@ -1766,50 +1790,48 @@ template <class Exp, class Ret> using ret_t = expected<Ret, err_t<Exp>>;
|
|||||||
template <class Exp, class F,
|
template <class Exp, class F,
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||||
*std::declval<Exp>())),
|
*std::declval<Exp>())),
|
||||||
detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr>
|
detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr>
|
||||||
constexpr auto and_then_impl(Exp &&exp, F &&f) {
|
constexpr auto and_then_impl(Exp &&exp, F &&f) {
|
||||||
static_assert(detail::is_expected<Ret>::value,
|
static_assert(detail::is_expected<Ret>::value, "F must return an expected");
|
||||||
"F must return an expected");
|
|
||||||
|
|
||||||
return exp.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
|
return exp.has_value()
|
||||||
: Ret(unexpect, exp.error());
|
? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
|
||||||
|
: Ret(unexpect, exp.error());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Exp, class F,
|
template <class Exp, class F,
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||||
*std::declval<Exp>())),
|
*std::declval<Exp>())),
|
||||||
detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr>
|
detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr>
|
||||||
constexpr auto and_then_impl(Exp &&exp, F &&f) {
|
constexpr auto and_then_impl(Exp &&exp, F &&f) {
|
||||||
static_assert(detail::is_expected<Ret>::value,
|
static_assert(detail::is_expected<Ret>::value, "F must return an expected");
|
||||||
"F must return an expected");
|
|
||||||
|
|
||||||
return exp.has_value() ? detail::invoke(std::forward<F>(f))
|
return exp.has_value() ? detail::invoke(std::forward<F>(f))
|
||||||
: Ret(unexpect, exp.error());
|
: Ret(unexpect, exp.error());
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
template<class>struct TC;
|
template <class> struct TC;
|
||||||
template <class Exp, class F,
|
template <class Exp, class F,
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||||
*std::declval<Exp>())),
|
*std::declval<Exp>())),
|
||||||
detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr>
|
detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * = nullptr>
|
||||||
auto and_then_impl(Exp &&exp, F &&f) -> Ret {
|
auto and_then_impl(Exp &&exp, F &&f) -> Ret {
|
||||||
static_assert(detail::is_expected<Ret>::value,
|
static_assert(detail::is_expected<Ret>::value, "F must return an expected");
|
||||||
"F must return an expected");
|
|
||||||
|
|
||||||
return exp.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
|
return exp.has_value()
|
||||||
: Ret(unexpect, exp.error());
|
? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
|
||||||
|
: Ret(unexpect, exp.error());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Exp, class F,
|
template <class Exp, class F,
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||||
*std::declval<Exp>())),
|
*std::declval<Exp>())),
|
||||||
detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr>
|
detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * = nullptr>
|
||||||
constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret {
|
constexpr auto and_then_impl(Exp &&exp, F &&f) -> Ret {
|
||||||
static_assert(detail::is_expected<Ret>::value,
|
static_assert(detail::is_expected<Ret>::value, "F must return an expected");
|
||||||
"F must return an expected");
|
|
||||||
|
|
||||||
return exp.has_value() ? detail::invoke(std::forward<F>(f))
|
return exp.has_value() ? detail::invoke(std::forward<F>(f))
|
||||||
: Ret(unexpect, exp.error());
|
: Ret(unexpect, exp.error());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1818,7 +1840,7 @@ template <class Exp, class F,
|
|||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||||
*std::declval<Exp>())),
|
*std::declval<Exp>())),
|
||||||
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
||||||
constexpr auto map_impl(Exp &&exp, F &&f) {
|
constexpr auto expected_map_impl(Exp &&exp, F &&f) {
|
||||||
using result = ret_t<Exp, detail::decay_t<Ret>>;
|
using result = ret_t<Exp, detail::decay_t<Ret>>;
|
||||||
return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
|
return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
|
||||||
*std::forward<Exp>(exp)))
|
*std::forward<Exp>(exp)))
|
||||||
@@ -1829,7 +1851,7 @@ template <class Exp, class F,
|
|||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||||
*std::declval<Exp>())),
|
*std::declval<Exp>())),
|
||||||
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
|
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
|
||||||
auto map_impl(Exp &&exp, F &&f) {
|
auto expected_map_impl(Exp &&exp, F &&f) {
|
||||||
using result = expected<void, err_t<Exp>>;
|
using result = expected<void, err_t<Exp>>;
|
||||||
if (exp.has_value()) {
|
if (exp.has_value()) {
|
||||||
detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
|
detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
|
||||||
@@ -1844,7 +1866,8 @@ template <class Exp, class F,
|
|||||||
*std::declval<Exp>())),
|
*std::declval<Exp>())),
|
||||||
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
||||||
|
|
||||||
constexpr auto map_impl(Exp &&exp, F &&f) -> ret_t<Exp, detail::decay_t<Ret>> {
|
constexpr auto expected_map_impl(Exp &&exp, F &&f)
|
||||||
|
-> ret_t<Exp, detail::decay_t<Ret>> {
|
||||||
using result = ret_t<Exp, detail::decay_t<Ret>>;
|
using result = ret_t<Exp, detail::decay_t<Ret>>;
|
||||||
|
|
||||||
return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
|
return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
|
||||||
@@ -1857,7 +1880,7 @@ template <class Exp, class F,
|
|||||||
*std::declval<Exp>())),
|
*std::declval<Exp>())),
|
||||||
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
|
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
|
||||||
|
|
||||||
auto map_impl(Exp &&exp, F &&f) -> expected<void, err_t<Exp>> {
|
auto expected_map_impl(Exp &&exp, F &&f) -> expected<void, err_t<Exp>> {
|
||||||
if (exp.has_value()) {
|
if (exp.has_value()) {
|
||||||
detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
|
detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
|
||||||
return {};
|
return {};
|
||||||
|
Reference in New Issue
Block a user