Skip to content

Commit ffb3771

Browse files
author
Tess Avitabile
committed
CXX-630 - Improve move semantics of model::write
1 parent 8092458 commit ffb3771

File tree

5 files changed

+53
-21
lines changed

5 files changed

+53
-21
lines changed

src/bsoncxx/view_or_value.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ class view_or_value {
8888
///
8989
/// Construct a view_or_value from a moved-in view_or_value.
9090
///
91-
BSONCXX_INLINE view_or_value(view_or_value&& other)
91+
/// TODO CXX-800: Create a noexcept expression to check the conditions that must be met.
92+
BSONCXX_INLINE view_or_value(view_or_value&& other) noexcept
9293
: _value{std::move(other._value)}, _view{_value ? _value->view() : std::move(other._view)} {
9394
other._view = View();
9495
other._value = stdx::nullopt;
@@ -97,7 +98,8 @@ class view_or_value {
9798
///
9899
/// Assign to this view_or_value from a moved-in view_or_value.
99100
///
100-
BSONCXX_INLINE view_or_value& operator=(view_or_value&& other) {
101+
/// TODO CXX-800: Create a noexcept expression to check the conditions that must be met.
102+
BSONCXX_INLINE view_or_value& operator=(view_or_value&& other) noexcept {
101103
_value = std::move(other._value);
102104
_view = _value ? _value->view() : std::move(other._view);
103105
other._view = View();

src/mongocxx/bulk_write.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,6 @@ void bulk_write::append(const model::write& operation) {
9090
upsert);
9191
break;
9292
}
93-
case write_type::k_uninitialized:
94-
break; // TODO: something exceptiony (see CXX-630)
9593
}
9694
}
9795

src/mongocxx/model/write.cpp

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
#include <type_traits>
16+
1517
#include <mongocxx/model/write.hpp>
1618

1719
#include <mongocxx/config/prelude.hpp>
@@ -21,23 +23,56 @@ MONGOCXX_INLINE_NAMESPACE_BEGIN
2123
namespace model {
2224

2325
write::write(insert_one value) : _type(write_type::k_insert_one), _insert_one(std::move(value)) {
26+
static_assert(std::is_nothrow_move_constructible<insert_one>::value, "Move-construct may throw");
27+
static_assert(std::is_nothrow_move_assignable<insert_one>::value, "Move-assign may throw");
2428
}
2529
write::write(delete_one value) : _type(write_type::k_delete_one), _delete_one(std::move(value)) {
30+
static_assert(std::is_nothrow_move_constructible<delete_one>::value, "Move-construct may throw");
31+
static_assert(std::is_nothrow_move_assignable<delete_one>::value, "Move-assign may throw");
2632
}
2733
write::write(delete_many value) : _type(write_type::k_delete_many), _delete_many(std::move(value)) {
34+
static_assert(std::is_nothrow_move_constructible<delete_many>::value, "Move-construct may throw");
35+
static_assert(std::is_nothrow_move_assignable<delete_many>::value, "Move-assign may throw");
2836
}
2937
write::write(update_one value) : _type(write_type::k_update_one), _update_one(std::move(value)) {
38+
static_assert(std::is_nothrow_move_constructible<update_one>::value, "Move-construct may throw");
39+
static_assert(std::is_nothrow_move_assignable<update_one>::value, "Move-assign may throw");
3040
}
3141
write::write(update_many value) : _type(write_type::k_update_many), _update_many(std::move(value)) {
42+
static_assert(std::is_nothrow_move_constructible<update_many>::value, "Move-construct may throw");
43+
static_assert(std::is_nothrow_move_assignable<update_many>::value, "Move-assign may throw");
3244
}
3345
write::write(replace_one value) : _type(write_type::k_replace_one), _replace_one(std::move(value)) {
46+
static_assert(std::is_nothrow_move_constructible<replace_one>::value, "Move-construct may throw");
47+
static_assert(std::is_nothrow_move_assignable<replace_one>::value, "Move-assign may throw");
3448
}
3549

36-
write::write(write&& rhs) noexcept : _type(write_type::k_uninitialized) {
37-
*this = std::move(rhs);
50+
write::write(write&& rhs) noexcept {
51+
switch (rhs._type) {
52+
case write_type::k_insert_one:
53+
new (&_insert_one) insert_one(std::move(rhs._insert_one));
54+
break;
55+
case write_type::k_update_one:
56+
new (&_update_one) update_one(std::move(rhs._update_one));
57+
break;
58+
case write_type::k_update_many:
59+
new (&_update_many) update_many(std::move(rhs._update_many));
60+
break;
61+
case write_type::k_delete_one:
62+
new (&_delete_one) delete_one(std::move(rhs._delete_one));
63+
break;
64+
case write_type::k_delete_many:
65+
new (&_delete_many) delete_many(std::move(rhs._delete_many));
66+
break;
67+
case write_type::k_replace_one:
68+
new (&_replace_one) replace_one(std::move(rhs._replace_one));
69+
break;
70+
}
71+
72+
_type = rhs._type;
3873
}
3974

40-
void write::destroy_member() {
75+
void write::destroy_member() noexcept {
4176
switch (_type) {
4277
case write_type::k_insert_one:
4378
_insert_one.~insert_one();
@@ -57,36 +92,34 @@ void write::destroy_member() {
5792
case write_type::k_replace_one:
5893
_replace_one.~replace_one();
5994
break;
60-
case write_type::k_uninitialized:
61-
break;
6295
}
63-
64-
_type = write_type::k_uninitialized;
6596
}
6697

6798
write& write::operator=(write&& rhs) noexcept {
99+
if (this == &rhs) {
100+
return *this;
101+
}
102+
68103
destroy_member();
69104

70105
switch (rhs._type) {
71106
case write_type::k_insert_one:
72-
_insert_one = std::move(rhs._insert_one);
107+
new (&_insert_one) insert_one(std::move(rhs._insert_one));
73108
break;
74109
case write_type::k_update_one:
75-
_update_one = std::move(rhs._update_one);
110+
new (&_update_one) update_one(std::move(rhs._update_one));
76111
break;
77112
case write_type::k_update_many:
78-
_update_many = std::move(rhs._update_many);
113+
new (&_update_many) update_many(std::move(rhs._update_many));
79114
break;
80115
case write_type::k_delete_one:
81-
_delete_one = std::move(rhs._delete_one);
116+
new (&_delete_one) delete_one(std::move(rhs._delete_one));
82117
break;
83118
case write_type::k_delete_many:
84-
_delete_many = std::move(rhs._delete_many);
119+
new (&_delete_many) delete_many(std::move(rhs._delete_many));
85120
break;
86121
case write_type::k_replace_one:
87-
_replace_one = std::move(rhs._replace_one);
88-
break;
89-
case write_type::k_uninitialized:
122+
new (&_replace_one) replace_one(std::move(rhs._replace_one));
90123
break;
91124
}
92125

src/mongocxx/model/write.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class MONGOCXX_API write {
5959
const replace_one& get_replace_one() const;
6060

6161
private:
62-
MONGOCXX_PRIVATE void destroy_member();
62+
MONGOCXX_PRIVATE void destroy_member() noexcept;
6363

6464
write_type _type;
6565

src/mongocxx/write_type.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ enum class write_type {
2626
k_update_one,
2727
k_update_many,
2828
k_replace_one,
29-
k_uninitialized,
3029
};
3130

3231
MONGOCXX_INLINE_NAMESPACE_END

0 commit comments

Comments
 (0)