summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorJacob Evans <jacob.evans@10gen.com>2020-04-03 15:06:52 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-09-29 02:41:46 +0000
commit684894759e5bf26d07aa5fe458aa6bed38907d03 (patch)
tree3439e7dadb8bfcb617fcc5348362b8eae0dec747 /src/mongo
parent875e21edd28047c6f6d78431a092271be7a74af7 (diff)
downloadmongo-684894759e5bf26d07aa5fe458aa6bed38907d03.tar.gz
SERVER-47327 Add composition member functions to StatusWith
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/base/status_with.h104
-rw-r--r--src/mongo/base/status_with_test.cpp433
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