forked from TartanLlama/optional
Fix map for reference types
This commit is contained in:
@@ -125,6 +125,11 @@ TEST_CASE("Monadic operations", "[monadic]") {
|
|||||||
auto o38r = o38.map([](int &i) -> const int & { return i; });
|
auto o38r = o38.map([](int &i) -> const int & { return i; });
|
||||||
REQUIRE(o38r);
|
REQUIRE(o38r);
|
||||||
REQUIRE(*o38r == 42);
|
REQUIRE(*o38r == 42);
|
||||||
|
|
||||||
|
int i = 42;
|
||||||
|
tl::optional<int&> o39 = i;
|
||||||
|
o39.map([](int& x){x = 12;});
|
||||||
|
REQUIRE(i == 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("map constexpr") {
|
SECTION("map constexpr") {
|
||||||
|
121
tl/optional.hpp
121
tl/optional.hpp
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
///
|
///
|
||||||
// optional - An implementation of std::optional with extensions
|
// optional - An implementation of std::optional with extensions
|
||||||
// Written in 2017 by Simon Brand (@TartanLlama)
|
// Written in 2017 by Simon Brand (@TartanLlama)
|
||||||
@@ -1597,6 +1598,59 @@ inline constexpr optional<T> make_optional(std::initializer_list<U> il,
|
|||||||
template <class T> optional(T)->optional<T>;
|
template <class T> optional(T)->optional<T>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/// \exclude
|
||||||
|
namespace detail {
|
||||||
|
#ifdef TL_OPTIONAL_CX14
|
||||||
|
template <class Opt, class F,
|
||||||
|
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||||
|
*std::declval<Opt>())),
|
||||||
|
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
||||||
|
constexpr auto map_impl(Opt &&opt, F &&f) {
|
||||||
|
return opt.has_value()
|
||||||
|
? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
|
||||||
|
: optional<detail::decay_t<Ret>>(nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Opt, class F,
|
||||||
|
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||||
|
*std::declval<Opt>())),
|
||||||
|
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
|
||||||
|
auto map_impl(Opt &&opt, F &&f) {
|
||||||
|
if (opt.has_value()) {
|
||||||
|
detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
|
||||||
|
return monostate{};
|
||||||
|
}
|
||||||
|
|
||||||
|
return optional<Ret>(nullopt);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template <class Opt, class F,
|
||||||
|
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||||
|
*std::declval<Opt>())),
|
||||||
|
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
||||||
|
|
||||||
|
constexpr auto map_impl(Opt &&opt, F &&f) -> optional<detail::decay_t<Ret>> {
|
||||||
|
return opt.has_value()
|
||||||
|
? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
|
||||||
|
: optional<detail::decay_t<Ret>>(nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Opt, class F,
|
||||||
|
class Ret = decltype(detail::invoke(std::declval<F>(),
|
||||||
|
*std::declval<Opt>())),
|
||||||
|
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
|
||||||
|
|
||||||
|
auto map_impl(Opt &&opt, F &&f) -> optional<monostate> {
|
||||||
|
if (opt.has_value()) {
|
||||||
|
detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
|
||||||
|
return monostate{};
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
/// Specialization for when `T` is a reference. `optional<T&>` acts similarly
|
/// Specialization for when `T` is a reference. `optional<T&>` acts similarly
|
||||||
/// to a `T*`, but provides more operations and shows intent more clearly.
|
/// to a `T*`, but provides more operations and shows intent more clearly.
|
||||||
///
|
///
|
||||||
@@ -1752,25 +1806,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_OPTIONAL_11_CONSTEXPR auto map(F &&f) & {
|
template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) & {
|
||||||
return map_impl(*this, std::forward<F>(f));
|
return detail::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_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {
|
template <class F> TL_OPTIONAL_11_CONSTEXPR auto map(F &&f) && {
|
||||||
return map_impl(std::move(*this), std::forward<F>(f));
|
return detail::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 detail::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 detail::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.
|
||||||
@@ -1786,7 +1840,7 @@ public:
|
|||||||
TL_OPTIONAL_11_CONSTEXPR decltype(map_impl(std::declval<optional &>(),
|
TL_OPTIONAL_11_CONSTEXPR decltype(map_impl(std::declval<optional &>(),
|
||||||
std::declval<F &&>()))
|
std::declval<F &&>()))
|
||||||
map(F &&f) & {
|
map(F &&f) & {
|
||||||
return map_impl(*this, std::forward<F>(f));
|
return detail::map_impl(*this, std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \group map
|
/// \group map
|
||||||
@@ -1795,7 +1849,7 @@ public:
|
|||||||
TL_OPTIONAL_11_CONSTEXPR decltype(map_impl(std::declval<optional &&>(),
|
TL_OPTIONAL_11_CONSTEXPR decltype(map_impl(std::declval<optional &&>(),
|
||||||
std::declval<F &&>()))
|
std::declval<F &&>()))
|
||||||
map(F &&f) && {
|
map(F &&f) && {
|
||||||
return map_impl(std::move(*this), std::forward<F>(f));
|
return detail::map_impl(std::move(*this), std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \group map
|
/// \group map
|
||||||
@@ -1804,7 +1858,7 @@ public:
|
|||||||
constexpr decltype(map_impl(std::declval<const optional &>(),
|
constexpr decltype(map_impl(std::declval<const optional &>(),
|
||||||
std::declval<F &&>()))
|
std::declval<F &&>()))
|
||||||
map(F &&f) const & {
|
map(F &&f) const & {
|
||||||
return map_impl(*this, std::forward<F>(f));
|
return detail::map_impl(*this, std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TL_OPTIONAL_NO_CONSTRR
|
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||||
@@ -1814,7 +1868,7 @@ public:
|
|||||||
constexpr decltype(map_impl(std::declval<const optional &&>(),
|
constexpr decltype(map_impl(std::declval<const optional &&>(),
|
||||||
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 detail::map_impl(std::move(*this), std::forward<F>(f));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@@ -2239,58 +2293,7 @@ private:
|
|||||||
T *m_value;
|
T *m_value;
|
||||||
}; // namespace tl
|
}; // namespace tl
|
||||||
|
|
||||||
/// \exclude
|
|
||||||
namespace detail {
|
|
||||||
#ifdef TL_OPTIONAL_CX14
|
|
||||||
template <class Opt, class F,
|
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
|
||||||
*std::declval<Opt>())),
|
|
||||||
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
|
||||||
constexpr auto map_impl(Opt &&opt, F &&f) {
|
|
||||||
return opt.has_value()
|
|
||||||
? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
|
|
||||||
: optional<detail::decay_t<Ret>>(nullopt);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Opt, class F,
|
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
|
||||||
*std::declval<Opt>())),
|
|
||||||
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
|
|
||||||
auto map_impl(Opt &&opt, F &&f) {
|
|
||||||
if (opt.has_value()) {
|
|
||||||
detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
|
|
||||||
return monostate{};
|
|
||||||
}
|
|
||||||
|
|
||||||
return optional<Ret>(nullopt);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
template <class Opt, class F,
|
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
|
||||||
*std::declval<Opt>())),
|
|
||||||
detail::enable_if_t<!std::is_void<Ret>::value> * = nullptr>
|
|
||||||
|
|
||||||
constexpr auto map_impl(Opt &&opt, F &&f) -> optional<detail::decay_t<Ret>> {
|
|
||||||
return opt.has_value()
|
|
||||||
? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt))
|
|
||||||
: optional<detail::decay_t<Ret>>(nullopt);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Opt, class F,
|
|
||||||
class Ret = decltype(detail::invoke(std::declval<F>(),
|
|
||||||
*std::declval<Opt>())),
|
|
||||||
detail::enable_if_t<std::is_void<Ret>::value> * = nullptr>
|
|
||||||
|
|
||||||
auto map_impl(Opt &&opt, F &&f) -> optional<monostate> {
|
|
||||||
if (opt.has_value()) {
|
|
||||||
detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt));
|
|
||||||
return monostate{};
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullopt;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
} // namespace tl
|
} // namespace tl
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user