Merge branch 'master' into trivial_copy_fix

This commit is contained in:
Simon Brand authored and GitHub committed 2017-12-05 20:19:46 +00:00
commit cb74470fc7
4 files changed
+139 -29

No files matched your search

+73 -28
View File
@@ -158,8 +158,8 @@ constexpr bool operator>=(const unexpected<E> &lhs, const unexpected<E> &rhs) {
/// *Example:*
/// auto e1 = tl::make_unexpected(42);
/// unexpected<int> e2 (42); //same semantics
template <class E> unexpected<E> make_unexpected(E &&e) {
return unexpected<E>(std::forward<E>(e));
template <class E> unexpected<typename std::decay<E>::type> make_unexpected(E &&e) {
return unexpected<typename std::decay<E>::type>(std::forward<E>(e));
}
/// \brief A tag type to tell expected to construct the unexpected value
@@ -631,7 +631,8 @@ struct expected_copy_base<T, E, false> : expected_operations_base<T, E> {
// move constructible
#ifndef TL_EXPECTED_GCC49
template <class T, class E,
bool = std::is_trivially_move_constructible<T>::value>
bool = std::is_trivially_move_constructible<T>::value
&& std::is_trivially_move_constructible<E>::value>
struct expected_move_base : expected_copy_base<T, E> {
using expected_copy_base<T, E>::expected_copy_base;
};
@@ -662,7 +663,10 @@ struct expected_move_base<T, E, false> : expected_copy_base<T, E> {
template <class T, class E,
bool = IS_TRIVIALLY_COPY_ASSIGNABLE(T) &&
IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) &&
IS_TRIVIALLY_DESTRUCTIBLE(T)>
IS_TRIVIALLY_DESTRUCTIBLE(T) &&
IS_TRIVIALLY_COPY_ASSIGNABLE(E) &&
IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E) &&
IS_TRIVIALLY_DESTRUCTIBLE(E)>
struct expected_copy_assign_base : expected_move_base<T, E> {
using expected_move_base<T, E>::expected_move_base;
};
@@ -691,8 +695,11 @@ struct expected_copy_assign_base<T, E, false> : expected_move_base<T, E> {
#ifndef TL_EXPECTED_GCC49
template <class T, class E,
bool = std::is_trivially_destructible<T>::value
&&std::is_trivially_move_constructible<T>::value
&&std::is_trivially_move_assignable<T>::value>
&&std::is_trivially_move_constructible<T>::value
&&std::is_trivially_move_assignable<T>::value
&&std::is_trivially_destructible<E>::value
&&std::is_trivially_move_constructible<E>::value
&&std::is_trivially_move_assignable<E>::value>
struct expected_move_assign_base : expected_copy_assign_base<T, E> {
using expected_copy_assign_base<T, E>::expected_copy_assign_base;
};
@@ -709,14 +716,17 @@ struct expected_move_assign_base<T, E, false>
expected_move_assign_base(const expected_move_assign_base &rhs) = default;
expected_move_assign_base(expected_move_assign_base &&rhs) = default;
expected_move_assign_base &
operator=(const expected_move_assign_base &rhs) = default;
expected_move_assign_base &
operator=(expected_move_assign_base &&rhs) noexcept(
std::is_nothrow_move_constructible<T>::value
&&std::is_nothrow_move_assignable<T>::value) {
this->assign(std::move(rhs));
return *this;
std::is_nothrow_move_constructible<T>::value
&&std::is_nothrow_move_assignable<T>::value) {
this->assign(std::move(rhs));
return *this;
}
};
@@ -929,9 +939,9 @@ public:
/// \group and_then
/// Carries out some operation which returns an expected on the stored object
/// if there is one. \requires `std::invoke(std::forward<F>(f), value())`
/// returns a `std::expected<U>` for some `U`. \returns Let `U` be the result
/// of `std::invoke(std::forward<F>(f), value())`. Returns a
/// `std::expected<U>`. The return value is empty if `*this` is empty,
/// returns an `expected<U>` for some `U`. \returns Let `U` be the result
/// of `std::invoke(std::forward<F>(f), value())`. Returns an
/// `expected<U>`. The return value is empty if `*this` is empty,
/// otherwise the return value of `std::invoke(std::forward<F>(f), value())`
/// is returned.
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
@@ -983,9 +993,9 @@ public:
/// \group and_then
/// Carries out some operation which returns an expected on the stored object
/// if there is one. \requires `std::invoke(std::forward<F>(f), value())`
/// returns a `std::expected<U>` for some `U`. \returns Let `U` be the result
/// of `std::invoke(std::forward<F>(f), value())`. Returns a
/// `std::expected<U>`. The return value is empty if `*this` is empty,
/// returns an `expected<U>` for some `U`. \returns Let `U` be the result
/// of `std::invoke(std::forward<F>(f), value())`. Returns an
/// `expected<U>`. The return value is empty if `*this` is empty,
/// otherwise the return value of `std::invoke(std::forward<F>(f), value())`
/// is returned.
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
@@ -1042,7 +1052,8 @@ public:
!defined(TL_EXPECTED_GCC54)
/// \brief Carries out some operation on the stored object if there is one.
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
/// value())`. Returns a `std::expected<U,E>`. If `*this` is unexpected, the
/// value())`. If `U` is `void`, returns an `expected<monostate,E>, otherwise
// returns an `expected<U,E>`. If `*this` is unexpected, the
/// result is `*this`, otherwise an `expected<U,E>` is constructed from the
/// return value of `std::invoke(std::forward<F>(f), value())` and is
/// returned.
@@ -1073,7 +1084,8 @@ public:
#else
/// \brief Carries out some operation on the stored object if there is one.
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
/// value())`. Returns a `std::expected<U,E>`. If `*this` is unexpected, the
/// value())`. If `U` is `void`, returns an `expected<monostate,E>, otherwise
// returns an `expected<U,E>`. If `*this` is unexpected, the
/// result is `*this`, otherwise an `expected<U,E>` is constructed from the
/// return value of `std::invoke(std::forward<F>(f), value())` and is
/// returned.
@@ -1122,7 +1134,8 @@ public:
/// \brief Carries out some operation on the stored unexpected object if there
/// is one.
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
/// value())`. Returns a `std::expected<T,U>`. If `*this` has an expected
/// value())`. If `U` is `void`, returns an `expected<T,monostate>`, otherwise
/// returns an `expected<T,U>`. If `*this` has an expected
/// value, the result is `*this`, otherwise an `expected<T,U>` is constructed
/// from `make_unexpected(std::invoke(std::forward<F>(f), value()))` and is
/// returned.
@@ -1154,7 +1167,7 @@ public:
/// \brief Carries out some operation on the stored unexpected object if there
/// is one.
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f),
/// value())`. Returns a `std::expected<T,U>`. If `*this` has an expected
/// value())`. Returns an `expected<T,U>`. If `*this` has an expected
/// value, the result is `*this`, otherwise an `expected<T,U>` is constructed
/// from `make_unexpected(std::invoke(std::forward<F>(f), value()))` and is
/// returned.
@@ -1630,6 +1643,7 @@ public:
/// \exclude
namespace detail {
template <class Exp> using exp_t = typename detail::decay_t<Exp>::error_type;
template <class Exp> using err_t = typename detail::decay_t<Exp>::error_type;
template <class Exp, class Ret> using ret_t = expected<Ret, err_t<Exp>>;
@@ -1639,7 +1653,7 @@ template <class Exp, class F,
*std::declval<Exp>())),
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
constexpr auto map_impl(Exp &&exp, F &&f) {
using result = ret_t<Exp, Ret>;
using result = ret_t<Exp, detail::decay_t<Ret>>;
return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
*std::forward<Exp>(exp)))
: result(unexpect, std::forward<Exp>(exp).error());
@@ -1664,8 +1678,8 @@ template <class Exp, class F,
*std::declval<Exp>())),
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
constexpr auto map_impl(Exp &&exp, F &&f) -> ret_t<Exp, Ret> {
using result = ret_t<Exp, Ret>;
constexpr auto map_impl(Exp &&exp, F &&f) -> 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),
*std::forward<Exp>(exp)))
@@ -1691,26 +1705,57 @@ auto map_impl(Exp &&exp, F &&f) -> expected<monostate, err_t<Exp>> {
!defined(TL_EXPECTED_GCC54)
template <class Exp, class 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>
constexpr auto map_error_impl(Exp &&exp, F &&f) {
using result = ret_t<Exp, Ret>;
using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
return exp.has_value()
? result(*std::forward<Exp>(exp))
: result(unexpect, detail::invoke(std::forward<F>(f),
std::forward<Exp>(exp).error()));
}
template <class Exp, class F,
class Ret = decltype(detail::invoke(std::declval<F>(),
*std::declval<Exp>())),
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
auto map_error_impl(Exp &&exp, F &&f) {
using result = expected<exp_t<Exp>, monostate>;
if (exp.has_value()) {
return result(*std::forward<Exp>(exp));
}
detail::invoke(std::forward<F>(f),
std::forward<Exp>(exp).error());
return result(unexpect, monostate{});
}
#else
template <class Exp, class F,
class Ret = decltype(detail::invoke(std::declval<F>(),
*std::declval<Exp>()))>
constexpr auto map_error_impl(Exp &&exp, F &&f) -> ret_t<Exp, Ret> {
using result = ret_t<Exp, Ret>;
*std::declval<Exp>())),
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
constexpr auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, detail::decay_t<Ret>> {
using result = ret_t<Exp, detail::decay_t<Ret>>;
return exp.has_value()
? result(*std::forward<Exp>(exp))
: result(unexpect, detail::invoke(std::forward<F>(f),
std::forward<Exp>(exp).error()));
}
template <class Exp, class F,
class Ret = decltype(detail::invoke(std::declval<F>(),
*std::declval<Exp>())),
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
using result = expected<exp_t<Exp>, monostate>;
if (exp.has_value()) {
return result(*std::forward<Exp>(exp));
}
detail::invoke(std::forward<F>(f),
std::forward<Exp>(exp).error());
return result(unexpect, monostate{});
}
#endif
template <class Exp, class F,