diff options
author | Jacob Evans <jacob.evans@10gen.com> | 2020-04-03 15:06:52 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-09-29 02:41:46 +0000 |
commit | 684894759e5bf26d07aa5fe458aa6bed38907d03 (patch) | |
tree | 3439e7dadb8bfcb617fcc5348362b8eae0dec747 /src/mongo | |
parent | 875e21edd28047c6f6d78431a092271be7a74af7 (diff) | |
download | mongo-684894759e5bf26d07aa5fe458aa6bed38907d03.tar.gz |
SERVER-47327 Add composition member functions to StatusWith
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/base/status_with.h | 104 | ||||
-rw-r--r-- | src/mongo/base/status_with_test.cpp | 433 |
2 files changed, 537 insertions, 0 deletions
diff --git a/src/mongo/base/status_with.h b/src/mongo/base/status_with.h index 79e5f1339af..b4e2654f815 100644 --- a/src/mongo/base/status_with.h +++ b/src/mongo/base/status_with.h @@ -163,6 +163,110 @@ public: } /** + * For any type U returned by a function f, transform creates a StatusWith<U> by either applying + * the function to the _t member or forwarding the _status. This is the lvalue overload. + */ + template <typename F> + StatusWith<std::invoke_result_t<F&&, T&>> transform(F&& f) & { + if (_t) + return {std::forward<F>(f)(*_t)}; + else + return {_status}; + } + + /** + * For any type U returned by a function f, transform creates a StatusWith<U> by either applying + * the function to the _t member or forwarding the _status. This is the const overload. + */ + template <typename F> + StatusWith<std::invoke_result_t<F&&, const T&>> transform(F&& f) const& { + if (_t) + return {std::forward<F>(f)(*_t)}; + else + return {_status}; + } + + /** + * For any type U returned by a function f, transform creates a StatusWith<U> by either applying + * the function to the _t member or forwarding the _status. This is the rvalue overload. + */ + template <typename F> + StatusWith<std::invoke_result_t<F&&, T&&>> transform(F&& f) && { + if (_t) + return {std::forward<F>(f)(*std::move(_t))}; + else + return {std::move(_status)}; + } + + /** + * For any type U returned by a function f, transform creates a StatusWith<U> by either applying + * the function to the _t member or forwarding the _status. This is the const rvalue overload. + */ + template <typename F> + StatusWith<std::invoke_result_t<F&&, const T&&>> transform(F&& f) const&& { + if (_t) + return {std::forward<F>(f)(*std::move(_t))}; + else + return {std::move(_status)}; + } + + /** + * For any type U returned inside a StatusWith<U> by a function f, andThen directly produces a + * StatusWith<U> by applying the function to the _t member or creates one by forwarding the + * _status. andThen performs the same function as transform but for a function f with a return + * type of StatusWith. This is the lvalue overload. + */ + template <typename F> + StatusWith<typename std::invoke_result_t<F&&, T&>::value_type> andThen(F&& f) & { + if (_t) + return {std::forward<F>(f)(*_t)}; + else + return {_status}; + } + + /** + * For any type U returned inside a StatusWith<U> by a function f, andThen directly produces a + * StatusWith<U> by applying the function to the _t member or creates one by forwarding the + * _status. andThen performs the same function as transform but for a function f with a return + * type of StatusWith. This is the const overload. + */ + template <typename F> + StatusWith<typename std::invoke_result_t<F&&, const T&>::value_type> andThen(F&& f) const& { + if (_t) + return {std::forward<F>(f)(*_t)}; + else + return {_status}; + } + + /** + * For any type U returned inside a StatusWith<U> by a function f, andThen directly produces a + * StatusWith<U> by applying the function to the _t member or creates one by forwarding the + * _status. andThen performs the same function as transform but for a function f with a return + * type of StatusWith. This is the rvalue overload. + */ + template <typename F> + StatusWith<typename std::invoke_result_t<F&&, T&&>::value_type> andThen(F&& f) && { + if (_t) + return {std::forward<F>(f)(*std::move(_t))}; + else + return {std::move(_status)}; + } + + /** + * For any type U returned inside a StatusWith<U> by a function f, andThen directly produces a + * StatusWith<U> by applying the function to the _t member or creates one by forwarding the + * _status. andThen performs the same function as transform but for a function f with a return + * type of StatusWith. This is the const rvalue overload. + */ + template <typename F> + StatusWith<typename std::invoke_result_t<F&&, const T&&>::value_type> andThen(F&& f) const&& { + if (_t) + return {std::forward<F>(f)(*std::move(_t))}; + else + return {std::move(_status)}; + } + + /** * This method is a transitional tool, to facilitate transition to compile-time enforced status * checking. * diff --git a/src/mongo/base/status_with_test.cpp b/src/mongo/base/status_with_test.cpp index 8ece2c2e7d0..d115815564e 100644 --- a/src/mongo/base/status_with_test.cpp +++ b/src/mongo/base/status_with_test.cpp @@ -28,8 +28,11 @@ */ #include <string> +#include <utility> #include <vector> +#include "mongo/base/error_codes.h" +#include "mongo/base/status.h" #include "mongo/base/status_with.h" #include "mongo/base/string_data.h" #include "mongo/unittest/unittest.h" @@ -89,5 +92,435 @@ TEST(StatusWith, ignoreTest) { [] { return StatusWith(false); }().getStatus().ignore(); } +TEST(StatusWith, MonadicTestLValue) { + { + auto from = StatusWith<int>{3}; + auto to = from.transform([](auto&& i) { return static_cast<double>(i); }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::transform returns incorrect type"); + ASSERT_EQ(3.0, to.getValue()); + } + { + auto from = StatusWith<int>{Status{ErrorCodes::IllegalOperation, "broke the law"}}; + auto to = from.transform([](auto&& i) { return static_cast<double>(i); }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::transform returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::IllegalOperation, "broke the law"), to.getStatus()); + } + { + auto from = StatusWith<int>{3}; + auto to = from.andThen([](auto&& i) { return StatusWith<double>{static_cast<double>(i)}; }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(3.0, to.getValue()); + } + { + auto from = StatusWith<int>{Status{ErrorCodes::IllegalOperation, "broke the law"}}; + auto to = from.andThen([](auto&& i) { return StatusWith<double>{static_cast<double>(i)}; }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::IllegalOperation, "broke the law"), to.getStatus()); + } + { + auto from = StatusWith<int>{3}; + auto to = from.andThen([](auto&& i) { + return StatusWith<double>{Status{ErrorCodes::BadValue, "lousy value"}}; + }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::BadValue, "lousy value"), to.getStatus()); + } + { + auto from = StatusWith<int>{Status{ErrorCodes::IllegalOperation, "broke the law"}}; + auto to = from.andThen([](auto&& i) { + return StatusWith<double>{Status{ErrorCodes::BadValue, "lousy value"}}; + }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::IllegalOperation, "broke the law"), to.getStatus()); + } +} + +TEST(StatusWith, MonadicTestConst) { + { + const auto from = StatusWith<int>{3}; + auto to = from.transform([](auto&& i) { return static_cast<double>(i); }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::transform returns incorrect type"); + ASSERT_EQ(3.0, to.getValue()); + } + { + const auto from = StatusWith<int>{Status{ErrorCodes::IllegalOperation, "broke the law"}}; + auto to = from.transform([](auto&& i) { return static_cast<double>(i); }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::transform returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::IllegalOperation, "broke the law"), to.getStatus()); + } + { + const auto from = StatusWith<int>{3}; + auto to = from.andThen([](auto&& i) { return StatusWith<double>{static_cast<double>(i)}; }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(3.0, to.getValue()); + } + { + const auto from = StatusWith<int>{Status{ErrorCodes::IllegalOperation, "broke the law"}}; + auto to = from.andThen([](auto&& i) { return StatusWith<double>{static_cast<double>(i)}; }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::IllegalOperation, "broke the law"), to.getStatus()); + } + { + const auto from = StatusWith<int>{3}; + auto to = from.andThen([](auto&& i) { + return StatusWith<double>{Status{ErrorCodes::BadValue, "lousy value"}}; + }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::BadValue, "lousy value"), to.getStatus()); + } + { + const auto from = StatusWith<int>{Status{ErrorCodes::IllegalOperation, "broke the law"}}; + auto to = from.andThen([](auto&& i) { + return StatusWith<double>{Status{ErrorCodes::BadValue, "lousy value"}}; + }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::IllegalOperation, "broke the law"), to.getStatus()); + } +} + +TEST(StatusWith, MonadicTestRValue) { + { + auto from = StatusWith<int>{3}; + auto to = std::move(from).transform([](auto&& i) { return static_cast<double>(i); }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::transform returns incorrect type"); + ASSERT_EQ(3.0, to.getValue()); + } + { + auto from = StatusWith<int>{Status{ErrorCodes::IllegalOperation, "broke the law"}}; + auto to = std::move(from).transform([](auto&& i) { return static_cast<double>(i); }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::transform returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::IllegalOperation, "broke the law"), to.getStatus()); + } + { + auto from = StatusWith<int>{3}; + auto to = std::move(from).andThen( + [](auto&& i) { return StatusWith<double>{static_cast<double>(i)}; }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(3.0, to.getValue()); + } + { + auto from = StatusWith<int>{Status{ErrorCodes::IllegalOperation, "broke the law"}}; + auto to = std::move(from).andThen( + [](auto&& i) { return StatusWith<double>{static_cast<double>(i)}; }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::IllegalOperation, "broke the law"), to.getStatus()); + } + { + auto from = StatusWith<int>{3}; + auto to = std::move(from).andThen([](auto&& i) { + return StatusWith<double>{Status{ErrorCodes::BadValue, "lousy value"}}; + }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::BadValue, "lousy value"), to.getStatus()); + } + { + auto from = StatusWith<int>{Status{ErrorCodes::IllegalOperation, "broke the law"}}; + auto to = std::move(from).andThen([](auto&& i) { + return StatusWith<double>{Status{ErrorCodes::BadValue, "lousy value"}}; + }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::IllegalOperation, "broke the law"), to.getStatus()); + } +} + +TEST(StatusWith, MonadicTestConstRValue) { + { + const auto from = StatusWith<int>{3}; + auto to = std::move(from).transform([](auto&& i) { return static_cast<double>(i); }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::transform returns incorrect type"); + ASSERT_EQ(3.0, to.getValue()); + } + { + const auto from = StatusWith<int>{Status{ErrorCodes::IllegalOperation, "broke the law"}}; + auto to = std::move(from).transform([](auto&& i) { return static_cast<double>(i); }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::transform returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::IllegalOperation, "broke the law"), to.getStatus()); + } + { + const auto from = StatusWith<int>{3}; + auto to = std::move(from).andThen( + [](auto&& i) { return StatusWith<double>{static_cast<double>(i)}; }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(3.0, to.getValue()); + } + { + const auto from = StatusWith<int>{Status{ErrorCodes::IllegalOperation, "broke the law"}}; + auto to = std::move(from).andThen( + [](auto&& i) { return StatusWith<double>{static_cast<double>(i)}; }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::IllegalOperation, "broke the law"), to.getStatus()); + } + { + const auto from = StatusWith<int>{3}; + auto to = std::move(from).andThen([](auto&& i) { + return StatusWith<double>{Status{ErrorCodes::BadValue, "lousy value"}}; + }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::BadValue, "lousy value"), to.getStatus()); + } + { + const auto from = StatusWith<int>{Status{ErrorCodes::IllegalOperation, "broke the law"}}; + auto to = std::move(from).andThen([](auto&& i) { + return StatusWith<double>{Status{ErrorCodes::BadValue, "lousy value"}}; + }); + static_assert(std::is_same_v<StatusWith<double>, decltype(to)>, + "StatusWith::andThen returns incorrect type"); + ASSERT_EQ(Status(ErrorCodes::IllegalOperation, "broke the law"), to.getStatus()); + } +} + +TEST(StatusWith, Overload) { + struct LValue {}; + struct Const {}; + struct RValue {}; + struct ConstRValue {}; + + struct { + auto operator()(int&) & { + return std::pair{LValue{}, LValue{}}; + } + auto operator()(const int&) & { + return std::pair{Const{}, LValue{}}; + } + auto operator()(int&&) & { + return std::pair{RValue{}, LValue{}}; + } + auto operator()(const int&&) & { + return std::pair{ConstRValue{}, LValue{}}; + } + + auto operator()(int&) const& { + return std::pair{LValue{}, Const{}}; + } + auto operator()(const int&) const& { + return std::pair{Const{}, Const{}}; + } + auto operator()(int&&) const& { + return std::pair{RValue{}, Const{}}; + } + auto operator()(const int&&) const& { + return std::pair{ConstRValue{}, Const{}}; + } + + auto operator()(int&) && { + return std::pair{LValue{}, RValue{}}; + } + auto operator()(const int&) && { + return std::pair{Const{}, RValue{}}; + } + auto operator()(int&&) && { + return std::pair{RValue{}, RValue{}}; + } + auto operator()(const int&&) && { + return std::pair{ConstRValue{}, RValue{}}; + } + + auto operator()(int&) const&& { + return std::pair{LValue{}, ConstRValue{}}; + } + auto operator()(const int&) const&& { + return std::pair{Const{}, ConstRValue{}}; + } + auto operator()(int&&) const&& { + return std::pair{RValue{}, ConstRValue{}}; + } + auto operator()(const int&&) const&& { + return std::pair{ConstRValue{}, ConstRValue{}}; + } + } transformFuncs; + struct { + auto operator()(int&) & { + return StatusWith{std::pair{LValue{}, LValue{}}}; + } + auto operator()(const int&) & { + return StatusWith{std::pair{Const{}, LValue{}}}; + } + auto operator()(int&&) & { + return StatusWith{std::pair{RValue{}, LValue{}}}; + } + auto operator()(const int&&) & { + return StatusWith{std::pair{ConstRValue{}, LValue{}}}; + } + + auto operator()(int&) const& { + return StatusWith{std::pair{LValue{}, Const{}}}; + } + auto operator()(const int&) const& { + return StatusWith{std::pair{Const{}, Const{}}}; + } + auto operator()(int&&) const& { + return StatusWith{std::pair{RValue{}, Const{}}}; + } + auto operator()(const int&&) const& { + return StatusWith{std::pair{ConstRValue{}, Const{}}}; + } + + auto operator()(int&) && { + return StatusWith{std::pair{LValue{}, RValue{}}}; + } + auto operator()(const int&) && { + return StatusWith{std::pair{Const{}, RValue{}}}; + } + auto operator()(int&&) && { + return StatusWith{std::pair{RValue{}, RValue{}}}; + } + auto operator()(const int&&) && { + return StatusWith{std::pair{ConstRValue{}, RValue{}}}; + } + + auto operator()(int&) const&& { + return StatusWith{std::pair{LValue{}, ConstRValue{}}}; + } + auto operator()(const int&) const&& { + return StatusWith{std::pair{Const{}, ConstRValue{}}}; + } + auto operator()(int&&) const&& { + return StatusWith{std::pair{RValue{}, ConstRValue{}}}; + } + auto operator()(const int&&) const&& { + return StatusWith{std::pair{ConstRValue{}, ConstRValue{}}}; + } + } andThenFuncs; + { + auto in = StatusWith<int>{3}; + static_assert(std::is_same_v<StatusWith<std::pair<LValue, LValue>>, + decltype(in.transform(transformFuncs))>, + "StatusWith::transform returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<LValue, LValue>>, + decltype(in.andThen(andThenFuncs))>, + "StatusWith::andThen returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<LValue, Const>>, + decltype(in.transform(std::as_const(transformFuncs)))>, + "StatusWith::transform returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<LValue, Const>>, + decltype(in.andThen(std::as_const(andThenFuncs)))>, + "StatusWith::andThen returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<LValue, RValue>>, + decltype(in.transform(std::move(transformFuncs)))>, + "StatusWith::transform returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<LValue, RValue>>, + decltype(in.andThen(std::move(andThenFuncs)))>, + "StatusWith::andThen returns incorrect type"); + static_assert( + std::is_same_v<StatusWith<std::pair<LValue, ConstRValue>>, + decltype(in.transform(std::move(std::as_const(transformFuncs))))>, + "StatusWith::transform returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<LValue, ConstRValue>>, + decltype(in.andThen(std::move(std::as_const(andThenFuncs))))>, + "StatusWith::andThen returns incorrect type"); + } + { + const auto in = StatusWith<int>{3}; + static_assert(std::is_same_v<StatusWith<std::pair<Const, LValue>>, + decltype(in.transform(transformFuncs))>, + "StatusWith::transform returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<Const, LValue>>, + decltype(in.andThen(andThenFuncs))>, + "StatusWith::andThen returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<Const, Const>>, + decltype(in.transform(std::as_const(transformFuncs)))>, + "StatusWith::transform returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<Const, Const>>, + decltype(in.andThen(std::as_const(andThenFuncs)))>, + "StatusWith::andThen returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<Const, RValue>>, + decltype(in.transform(std::move(transformFuncs)))>, + "StatusWith::transform returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<Const, RValue>>, + decltype(in.andThen(std::move(andThenFuncs)))>, + "StatusWith::andThen returns incorrect type"); + static_assert( + std::is_same_v<StatusWith<std::pair<Const, ConstRValue>>, + decltype(in.transform(std::move(std::as_const(transformFuncs))))>, + "StatusWith::transform returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<Const, ConstRValue>>, + decltype(in.andThen(std::move(std::as_const(andThenFuncs))))>, + "StatusWith::andThen returns incorrect type"); + } + { + auto in = StatusWith<int>{3}; + static_assert(std::is_same_v<StatusWith<std::pair<RValue, LValue>>, + decltype(std::move(in).transform(transformFuncs))>, + "StatusWith::transform returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<RValue, LValue>>, + decltype(std::move(in).andThen(andThenFuncs))>, + "StatusWith::andThen returns incorrect type"); + static_assert( + std::is_same_v<StatusWith<std::pair<RValue, Const>>, + decltype(std::move(in).transform(std::as_const(transformFuncs)))>, + "StatusWith::transform returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<RValue, Const>>, + decltype(std::move(in).andThen(std::as_const(andThenFuncs)))>, + "StatusWith::andThen returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<RValue, RValue>>, + decltype(std::move(in).transform(std::move(transformFuncs)))>, + "StatusWith::transform returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<RValue, RValue>>, + decltype(std::move(in).andThen(std::move(andThenFuncs)))>, + "StatusWith::andThen returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<RValue, ConstRValue>>, + decltype(std::move(in).transform( + std::move(std::as_const(transformFuncs))))>, + "StatusWith::transform returns incorrect type"); + static_assert( + std::is_same_v<StatusWith<std::pair<RValue, ConstRValue>>, + decltype(std::move(in).andThen(std::move(std::as_const(andThenFuncs))))>, + "StatusWith::andThen returns incorrect type"); + } + { + const auto in = StatusWith<int>{3}; + static_assert(std::is_same_v<StatusWith<std::pair<ConstRValue, LValue>>, + decltype(std::move(in).transform(transformFuncs))>, + "StatusWith::transform returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<ConstRValue, LValue>>, + decltype(std::move(in).andThen(andThenFuncs))>, + "StatusWith::andThen returns incorrect type"); + static_assert( + std::is_same_v<StatusWith<std::pair<ConstRValue, Const>>, + decltype(std::move(in).transform(std::as_const(transformFuncs)))>, + "StatusWith::transform returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<ConstRValue, Const>>, + decltype(std::move(in).andThen(std::as_const(andThenFuncs)))>, + "StatusWith::andThen returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<ConstRValue, RValue>>, + decltype(std::move(in).transform(std::move(transformFuncs)))>, + "StatusWith::transform returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<ConstRValue, RValue>>, + decltype(std::move(in).andThen(std::move(andThenFuncs)))>, + "StatusWith::andThen returns incorrect type"); + static_assert(std::is_same_v<StatusWith<std::pair<ConstRValue, ConstRValue>>, + decltype(std::move(in).transform( + std::move(std::as_const(transformFuncs))))>, + "StatusWith::transform returns incorrect type"); + static_assert( + std::is_same_v<StatusWith<std::pair<ConstRValue, ConstRValue>>, + decltype(std::move(in).andThen(std::move(std::as_const(andThenFuncs))))>, + "StatusWith::andThen returns incorrect type"); + } +} + } // namespace } // namespace mongo |