Skip to content

Commit b69fdf9

Browse files
author
Pierre-Luc Gagné
committed
Improve numeric optional POD overloads and add unit tests
1 parent 1d5da05 commit b69fdf9

2 files changed

Lines changed: 86 additions & 34 deletions

File tree

lib/include/ds_mysql/column_field_base_numeric.hpp

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,15 @@ struct base<float_type<Precision, Scale>> : column_field_tag {
2424
std::is_nothrow_move_constructible_v<float_type<Precision, Scale>>)
2525
: value(std::move(v)) {
2626
}
27+
constexpr base(float v) noexcept : value(v) {
28+
}
2729

2830
constexpr base& operator=(float_type<Precision, Scale> v) noexcept(
2931
std::is_nothrow_move_assignable_v<float_type<Precision, Scale>>) {
3032
value = std::move(v);
3133
return *this;
3234
}
3335

34-
// Constructors and assignments from POD float type
35-
constexpr base(float v) noexcept : value(v) {
36-
}
37-
3836
constexpr base& operator=(float v) noexcept {
3937
value = v;
4038
return *this;
@@ -68,10 +66,15 @@ struct base<std::optional<float_type<Precision, Scale>>> : column_field_tag {
6866
std::is_nothrow_move_constructible_v<float_type<Precision, Scale>>)
6967
: value(std::move(v)) {
7068
}
69+
constexpr base(float v) noexcept : value(v) {
70+
}
7171
constexpr base(std::optional<float_type<Precision, Scale>> v) noexcept(
7272
std::is_nothrow_move_constructible_v<std::optional<float_type<Precision, Scale>>>)
7373
: value(std::move(v)) {
7474
}
75+
constexpr base(std::optional<float> v) noexcept
76+
: value(v ? std::optional<float_type<Precision, Scale>>{*v} : std::nullopt) {
77+
}
7578

7679
constexpr base& operator=(std::nullopt_t) noexcept {
7780
value = std::nullopt;
@@ -87,15 +90,14 @@ struct base<std::optional<float_type<Precision, Scale>>> : column_field_tag {
8790
value = std::move(v);
8891
return *this;
8992
}
90-
91-
// Constructors and assignments from POD float type
92-
constexpr base(float v) noexcept : value(v) {
93-
}
94-
9593
constexpr base& operator=(float v) noexcept {
9694
value = v;
9795
return *this;
9896
}
97+
constexpr base& operator=(std::optional<float> v) noexcept {
98+
value = v ? std::optional<float_type<Precision, Scale>>{*v} : std::nullopt;
99+
return *this;
100+
}
99101

100102
[[nodiscard]] constexpr std::optional<float_type<Precision, Scale>> const& get() const noexcept {
101103
return value;
@@ -127,17 +129,15 @@ struct base<double_type<Precision, Scale>> : column_field_tag {
127129
std::is_nothrow_move_constructible_v<double_type<Precision, Scale>>)
128130
: value(std::move(v)) {
129131
}
132+
constexpr base(double v) noexcept : value(v) {
133+
}
130134

131135
constexpr base& operator=(double_type<Precision, Scale> v) noexcept(
132136
std::is_nothrow_move_assignable_v<double_type<Precision, Scale>>) {
133137
value = std::move(v);
134138
return *this;
135139
}
136140

137-
// Constructors and assignments from POD double type
138-
constexpr base(double v) noexcept : value(v) {
139-
}
140-
141141
constexpr base& operator=(double v) noexcept {
142142
value = v;
143143
return *this;
@@ -171,10 +171,15 @@ struct base<std::optional<double_type<Precision, Scale>>> : column_field_tag {
171171
std::is_nothrow_move_constructible_v<double_type<Precision, Scale>>)
172172
: value(std::move(v)) {
173173
}
174+
constexpr base(double v) noexcept : value(v) {
175+
}
174176
constexpr base(std::optional<double_type<Precision, Scale>> v) noexcept(
175177
std::is_nothrow_move_constructible_v<std::optional<double_type<Precision, Scale>>>)
176178
: value(std::move(v)) {
177179
}
180+
constexpr base(std::optional<double> v) noexcept
181+
: value(v ? std::optional<double_type<Precision, Scale>>{*v} : std::nullopt) {
182+
}
178183

179184
constexpr base& operator=(std::nullopt_t) noexcept {
180185
value = std::nullopt;
@@ -190,15 +195,14 @@ struct base<std::optional<double_type<Precision, Scale>>> : column_field_tag {
190195
value = std::move(v);
191196
return *this;
192197
}
193-
194-
// Constructors and assignments from POD double type
195-
constexpr base(double v) noexcept : value(v) {
196-
}
197-
198198
constexpr base& operator=(double v) noexcept {
199199
value = v;
200200
return *this;
201201
}
202+
constexpr base& operator=(std::optional<double> v) noexcept {
203+
value = v ? std::optional<double_type<Precision, Scale>>{*v} : std::nullopt;
204+
return *this;
205+
}
202206

203207
[[nodiscard]] constexpr std::optional<double_type<Precision, Scale>> const& get() const noexcept {
204208
return value;
@@ -230,20 +234,18 @@ struct base<decimal_type<Precision, Scale>> : column_field_tag {
230234
std::is_nothrow_move_constructible_v<decimal_type<Precision, Scale>>)
231235
: value(std::move(v)) {
232236
}
237+
constexpr base(double v) noexcept : value(v) {
238+
}
239+
240+
constexpr base(long double v) noexcept : value(static_cast<double>(v)) {
241+
}
233242

234243
constexpr base& operator=(decimal_type<Precision, Scale> v) noexcept(
235244
std::is_nothrow_move_assignable_v<decimal_type<Precision, Scale>>) {
236245
value = std::move(v);
237246
return *this;
238247
}
239248

240-
// Constructors and assignments from POD double and long double types
241-
constexpr base(double v) noexcept : value(v) {
242-
}
243-
244-
constexpr base(long double v) noexcept : value(static_cast<double>(v)) {
245-
}
246-
247249
constexpr base& operator=(double v) noexcept {
248250
value = v;
249251
return *this;
@@ -282,10 +284,17 @@ struct base<std::optional<decimal_type<Precision, Scale>>> : column_field_tag {
282284
std::is_nothrow_move_constructible_v<decimal_type<Precision, Scale>>)
283285
: value(std::move(v)) {
284286
}
287+
constexpr base(double v) noexcept : value(v) {
288+
}
289+
constexpr base(long double v) noexcept : value(static_cast<double>(v)) {
290+
}
285291
constexpr base(std::optional<decimal_type<Precision, Scale>> v) noexcept(
286292
std::is_nothrow_move_constructible_v<std::optional<decimal_type<Precision, Scale>>>)
287293
: value(std::move(v)) {
288294
}
295+
constexpr base(std::optional<double> v) noexcept
296+
: value(v ? std::optional<decimal_type<Precision, Scale>>{*v} : std::nullopt) {
297+
}
289298

290299
constexpr base& operator=(std::nullopt_t) noexcept {
291300
value = std::nullopt;
@@ -302,13 +311,6 @@ struct base<std::optional<decimal_type<Precision, Scale>>> : column_field_tag {
302311
return *this;
303312
}
304313

305-
// Constructors and assignments from POD double and long double types
306-
constexpr base(double v) noexcept : value(v) {
307-
}
308-
309-
constexpr base(long double v) noexcept : value(static_cast<double>(v)) {
310-
}
311-
312314
constexpr base& operator=(double v) noexcept {
313315
value = v;
314316
return *this;
@@ -318,6 +320,10 @@ struct base<std::optional<decimal_type<Precision, Scale>>> : column_field_tag {
318320
value = static_cast<double>(v);
319321
return *this;
320322
}
323+
constexpr base& operator=(std::optional<double> v) noexcept {
324+
value = v ? std::optional<decimal_type<Precision, Scale>>{*v} : std::nullopt;
325+
return *this;
326+
}
321327

322328
[[nodiscard]] constexpr std::optional<decimal_type<Precision, Scale>> const& get() const noexcept {
323329
return value;

tests/unit/test_field_types.cpp

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
#include <boost/ut.hpp>
2+
#include <optional>
23
#include <string>
34
#include <string_view>
45

56
#include "ds_mysql/column_field.hpp"
7+
#include "ds_mysql/config.hpp"
68
#include "ds_mysql/credentials.hpp"
79
#include "ds_mysql/database_name.hpp"
810
#include "ds_mysql/host_name.hpp"
9-
#include "ds_mysql/config.hpp"
1011
#include "ds_mysql/port_number.hpp"
1112
#include "ds_mysql/sql_identifiers.hpp"
13+
#include "ds_mysql/sql_numeric.hpp"
1214
#include "ds_mysql/sql_text.hpp"
15+
#include "ds_mysql/sql_varchar.hpp"
1316
#include "ds_mysql/user_name.hpp"
1417
#include "ds_mysql/user_password.hpp"
15-
#include "ds_mysql/sql_varchar.hpp"
1618
#include "ds_mysql/version.hpp"
1719

1820
using namespace boost::ut;
@@ -218,6 +220,50 @@ suite<"column_field string constructors"> column_field_string_suite = [] {
218220
};
219221
};
220222

223+
suite<"column_field numeric optional POD interop"> column_field_numeric_optional_pod_suite = [] {
224+
"optional<float_type> construct from optional<float> (value)"_test = [] {
225+
using col_t = column_field<"f", std::optional<float_type<10, 2>>>;
226+
col_t col{std::optional<float>{12.5f}};
227+
expect(fatal(col.value.has_value()));
228+
expect(col.value->get() == 12.5f);
229+
};
230+
231+
"optional<float_type> assign from optional<float> (nullopt)"_test = [] {
232+
using col_t = column_field<"f", std::optional<float_type<10, 2>>>;
233+
col_t col{1.0f};
234+
col = std::optional<float>{};
235+
expect(!col.value.has_value());
236+
};
237+
238+
"optional<double_type> construct from optional<double> (value)"_test = [] {
239+
using col_t = column_field<"d", std::optional<double_type<12, 4>>>;
240+
col_t col{std::optional<double>{123.4567}};
241+
expect(fatal(col.value.has_value()));
242+
expect(col.value->get() == 123.4567);
243+
};
244+
245+
"optional<double_type> assign from optional<double> (nullopt)"_test = [] {
246+
using col_t = column_field<"d", std::optional<double_type<12, 4>>>;
247+
col_t col{42.0};
248+
col = std::optional<double>{};
249+
expect(!col.value.has_value());
250+
};
251+
252+
"optional<decimal_type> construct from optional<double> (value)"_test = [] {
253+
using col_t = column_field<"m", std::optional<decimal_type<18, 6>>>;
254+
col_t col{std::optional<double>{99.123456}};
255+
expect(fatal(col.value.has_value()));
256+
expect(col.value->get() == 99.123456);
257+
};
258+
259+
"optional<decimal_type> assign from optional<double> (nullopt)"_test = [] {
260+
using col_t = column_field<"m", std::optional<decimal_type<18, 6>>>;
261+
col_t col{9.0};
262+
col = std::optional<double>{};
263+
expect(!col.value.has_value());
264+
};
265+
};
266+
221267
// ===================================================================
222268
// version
223269
// ===================================================================

0 commit comments

Comments
 (0)