Skip to content

Commit dd2040e

Browse files
committed
Added the "unary minus" operator
1 parent 766861e commit dd2040e

File tree

10 files changed

+120
-17
lines changed

10 files changed

+120
-17
lines changed

dev/column_result.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,11 @@ namespace sqlite_orm {
149149
using type = std::string;
150150
};
151151

152+
template<class DBOs, class T>
153+
struct column_result_t<DBOs, unary_minus_t<T>, void> {
154+
using type = double;
155+
};
156+
152157
template<class DBOs, class L, class R>
153158
struct column_result_t<DBOs, add_t<L, R>, void> {
154159
using type = double;

dev/core_functions.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,6 +2041,14 @@ namespace sqlite_orm {
20412041
// Intentionally place operators for types classified as arithmetic or general operator arguments in the internal namespace
20422042
// to facilitate ADL (Argument Dependent Lookup)
20432043
namespace internal {
2044+
template<
2045+
class T,
2046+
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, T>, is_operator_argument<T>>::value,
2047+
bool> = true>
2048+
constexpr unary_minus_t<unwrap_expression_t<T>> operator-(T arg) {
2049+
return {get_from_expression(std::forward<T>(arg))};
2050+
}
2051+
20442052
template<class L,
20452053
class R,
20462054
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,

dev/node_tuple.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ namespace sqlite_orm {
199199
template<class C>
200200
struct node_tuple<negated_condition_t<C>, void> : node_tuple<C> {};
201201

202+
template<class T>
203+
struct node_tuple<unary_minus_t<T>, void> : node_tuple<T> {};
204+
202205
template<class T>
203206
struct node_tuple<bitwise_not_t<T>, void> : node_tuple<T> {};
204207

dev/operators.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,24 @@ namespace sqlite_orm {
4141
template<class L, class R>
4242
using conc_t = binary_operator<L, R, conc_string>;
4343

44+
struct unary_minus_string {
45+
serialize_result_type serialize() const {
46+
return "-";
47+
}
48+
};
49+
50+
/**
51+
* Result of unary minus - operator
52+
*/
53+
template<class T>
54+
struct unary_minus_t : unary_minus_string, arithmetic_t, negatable_t {
55+
using argument_type = T;
56+
57+
argument_type argument;
58+
59+
unary_minus_t(argument_type argument_) : argument(std::move(argument_)) {}
60+
};
61+
4462
struct add_string {
4563
serialize_result_type serialize() const {
4664
return "+";
@@ -60,7 +78,7 @@ namespace sqlite_orm {
6078
};
6179

6280
/**
63-
* Result of substitute - operator
81+
* Result of substraction - operator
6482
*/
6583
template<class L, class R>
6684
using sub_t = binary_operator<L, R, sub_string, arithmetic_t, negatable_t>;
@@ -201,6 +219,11 @@ namespace sqlite_orm {
201219
return {std::move(l), std::move(r)};
202220
}
203221

222+
template<class T>
223+
constexpr internal::unary_minus_t<T> minus(T t) {
224+
return {std::move(t)};
225+
}
226+
204227
/**
205228
* Public interface for + operator. Example: `select(add(&User::age, 100));` => SELECT age + 100 FROM users
206229
*/

dev/statement_serializer.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -718,8 +718,11 @@ namespace sqlite_orm {
718718
};
719719

720720
template<class T>
721-
struct statement_serializer<bitwise_not_t<T>, void> {
722-
using statement_type = bitwise_not_t<T>;
721+
struct statement_serializer<
722+
T,
723+
std::enable_if_t<polyfill::disjunction<polyfill::is_specialization_of<T, unary_minus_t>,
724+
polyfill::is_specialization_of<T, bitwise_not_t>>::value>> {
725+
using statement_type = T;
723726

724727
template<class Ctx>
725728
std::string operator()(const statement_type& expression, const Ctx& context) const {

include/sqlite_orm/sqlite_orm.h

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4168,6 +4168,24 @@ namespace sqlite_orm {
41684168
template<class L, class R>
41694169
using conc_t = binary_operator<L, R, conc_string>;
41704170

4171+
struct unary_minus_string {
4172+
serialize_result_type serialize() const {
4173+
return "-";
4174+
}
4175+
};
4176+
4177+
/**
4178+
* Result of unary minus - operator
4179+
*/
4180+
template<class T>
4181+
struct unary_minus_t : unary_minus_string, arithmetic_t, negatable_t {
4182+
using argument_type = T;
4183+
4184+
argument_type argument;
4185+
4186+
unary_minus_t(argument_type argument_) : argument(std::move(argument_)) {}
4187+
};
4188+
41714189
struct add_string {
41724190
serialize_result_type serialize() const {
41734191
return "+";
@@ -4187,7 +4205,7 @@ namespace sqlite_orm {
41874205
};
41884206

41894207
/**
4190-
* Result of substitute - operator
4208+
* Result of substraction - operator
41914209
*/
41924210
template<class L, class R>
41934211
using sub_t = binary_operator<L, R, sub_string, arithmetic_t, negatable_t>;
@@ -4328,6 +4346,11 @@ namespace sqlite_orm {
43284346
return {std::move(l), std::move(r)};
43294347
}
43304348

4349+
template<class T>
4350+
constexpr internal::unary_minus_t<T> minus(T t) {
4351+
return {std::move(t)};
4352+
}
4353+
43314354
/**
43324355
* Public interface for + operator. Example: `select(add(&User::age, 100));` => SELECT age + 100 FROM users
43334356
*/
@@ -8091,6 +8114,14 @@ namespace sqlite_orm {
80918114
// Intentionally place operators for types classified as arithmetic or general operator arguments in the internal namespace
80928115
// to facilitate ADL (Argument Dependent Lookup)
80938116
namespace internal {
8117+
template<
8118+
class T,
8119+
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, T>, is_operator_argument<T>>::value,
8120+
bool> = true>
8121+
constexpr unary_minus_t<unwrap_expression_t<T>> operator-(T arg) {
8122+
return {get_from_expression(std::forward<T>(arg))};
8123+
}
8124+
80948125
template<class L,
80958126
class R,
80968127
std::enable_if_t<polyfill::disjunction<std::is_base_of<arithmetic_t, L>,
@@ -11474,6 +11505,11 @@ namespace sqlite_orm {
1147411505
using type = std::string;
1147511506
};
1147611507

11508+
template<class DBOs, class T>
11509+
struct column_result_t<DBOs, unary_minus_t<T>, void> {
11510+
using type = double;
11511+
};
11512+
1147711513
template<class DBOs, class L, class R>
1147811514
struct column_result_t<DBOs, add_t<L, R>, void> {
1147911515
using type = double;
@@ -19941,8 +19977,11 @@ namespace sqlite_orm {
1994119977
};
1994219978

1994319979
template<class T>
19944-
struct statement_serializer<bitwise_not_t<T>, void> {
19945-
using statement_type = bitwise_not_t<T>;
19980+
struct statement_serializer<
19981+
T,
19982+
std::enable_if_t<polyfill::disjunction<polyfill::is_specialization_of<T, unary_minus_t>,
19983+
polyfill::is_specialization_of<T, bitwise_not_t>>::value>> {
19984+
using statement_type = T;
1994619985

1994719986
template<class Ctx>
1994819987
std::string operator()(const statement_type& expression, const Ctx& context) const {
@@ -24287,6 +24326,9 @@ namespace sqlite_orm {
2428724326
template<class C>
2428824327
struct node_tuple<negated_condition_t<C>, void> : node_tuple<C> {};
2428924328

24329+
template<class T>
24330+
struct node_tuple<unary_minus_t<T>, void> : node_tuple<T> {};
24331+
2429024332
template<class T>
2429124333
struct node_tuple<bitwise_not_t<T>, void> : node_tuple<T> {};
2429224334

tests/statement_serializer_tests/arithmetic_operators.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ TEST_CASE("statement_serializer arithmetic operators") {
88
internal::serializer_context<internal::db_objects_tuple<>> context{storage};
99
std::string value;
1010
decltype(value) expected;
11+
SECTION("unary minus") {
12+
SECTION("func") {
13+
value = serialize(minus(20), context);
14+
}
15+
SECTION("operator") {
16+
value = serialize(-c(20), context);
17+
}
18+
expected = "-20";
19+
}
1120
SECTION("add") {
1221
SECTION("func") {
1322
value = serialize(add(3, 5), context);
@@ -55,12 +64,12 @@ TEST_CASE("statement_serializer arithmetic operators") {
5564
}
5665
SECTION("parentheses keeping order of precedence") {
5766
SECTION("1") {
58-
value = serialize(c(4) + 5 + 3, context);
59-
expected = "(4 + 5) + 3";
67+
value = serialize(c(4) + 5 + -c(3), context);
68+
expected = "(4 + 5) + -3";
6069
}
6170
SECTION("2") {
62-
value = serialize(4 + (c(5) + 3), context);
63-
expected = "4 + (5 + 3)";
71+
value = serialize(4 + -(c(5) + 3), context);
72+
expected = "4 + -(5 + 3)";
6473
}
6574
SECTION("3") {
6675
value = serialize(4 + c(5) * 3 + 1, context);

tests/static_tests/column_result_t.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ TEST_CASE("column_result_of_t") {
9595
runTest<db_objects_t, std::string>(all(&User::name));
9696
runTest<db_objects_t, std::string>(conc(&User::name, &User::id));
9797
runTest<db_objects_t, std::string>(c(&User::name) || &User::id);
98+
runTest<db_objects_t, double>(minus(&User::id));
99+
runTest<db_objects_t, double>(-c(&User::id));
98100
runTest<db_objects_t, double>(add(&User::id, 5));
99101
runTest<db_objects_t, double>(c(&User::id) + 5);
100102
runTest<db_objects_t, double>(sub(&User::id, 5));

tests/static_tests/node_tuple.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -189,25 +189,28 @@ TEST_CASE("Node tuple") {
189189
using namespace internal;
190190

191191
using CondTuple = node_tuple_t<conc_t<std::string, decltype(&User::name)>>;
192-
static_assert(is_same<CondTuple, tuple<std::string, decltype(&User::name)>>::value, "conc_t");
192+
STATIC_REQUIRE(is_same<CondTuple, tuple<std::string, decltype(&User::name)>>::value);
193+
194+
using MinusTuple = node_tuple_t<unary_minus_t<decltype(&User::id)>>;
195+
STATIC_REQUIRE(is_same<MinusTuple, tuple<decltype(&User::id)>>::value);
193196

194197
using AddTuple = node_tuple_t<add_t<int, decltype(&User::id)>>;
195-
static_assert(is_same<AddTuple, tuple<int, decltype(&User::id)>>::value, "add_t");
198+
STATIC_REQUIRE(is_same<AddTuple, tuple<int, decltype(&User::id)>>::value);
196199

197200
using SubTuple = node_tuple_t<sub_t<float, double>>;
198-
static_assert(is_same<SubTuple, tuple<float, double>>::value, "sub_t");
201+
STATIC_REQUIRE(is_same<SubTuple, tuple<float, double>>::value);
199202

200203
using MulTuple = node_tuple_t<mul_t<double, decltype(&User::id)>>;
201-
static_assert(is_same<MulTuple, tuple<double, decltype(&User::id)>>::value, "mul_t");
204+
STATIC_REQUIRE(is_same<MulTuple, tuple<double, decltype(&User::id)>>::value);
202205

203206
using DivTuple = node_tuple_t<sqlite_orm::internal::div_t<int, float>>;
204-
static_assert(is_same<DivTuple, tuple<int, float>>::value, "div_t");
207+
STATIC_REQUIRE(is_same<DivTuple, tuple<int, float>>::value);
205208

206209
using ModTuple = node_tuple_t<mod_t<decltype(&User::id), int>>;
207-
static_assert(is_same<ModTuple, tuple<decltype(&User::id), int>>::value, "mod_t");
210+
STATIC_REQUIRE(is_same<ModTuple, tuple<decltype(&User::id), int>>::value);
208211

209212
using AssignTuple = node_tuple_t<assign_t<decltype(&User::name), std::string>>;
210-
static_assert(is_same<AssignTuple, tuple<decltype(&User::name), std::string>>::value, "assign_t");
213+
STATIC_REQUIRE(is_same<AssignTuple, tuple<decltype(&User::name), std::string>>::value);
211214
}
212215
SECTION("bitwise operator") {
213216
using namespace internal;

tests/static_tests/operators_adl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ using sqlite_orm::internal::less_or_equal_t;
2828
using sqlite_orm::internal::less_than_t;
2929
using sqlite_orm::internal::negated_condition_t;
3030
using sqlite_orm::internal::or_condition_t;
31+
using sqlite_orm::internal::unary_minus_t;
3132
using sqlite_orm::polyfill::is_specialization_of_v;
3233

3334
template<class E>
@@ -68,6 +69,10 @@ void runTests(E expression) {
6869
STATIC_REQUIRE(is_specialization_of_v<decltype(42 || (expression || 42)), binary_operator>);
6970
STATIC_REQUIRE(is_specialization_of_v<decltype(c(42) || (expression || 42)), binary_operator>);
7071

72+
STATIC_REQUIRE(is_specialization_of_v<decltype(-expression), unary_minus_t>);
73+
STATIC_REQUIRE(is_specialization_of_v<decltype(-(expression + expression)), unary_minus_t>);
74+
STATIC_REQUIRE(is_specialization_of_v<decltype(-expression + expression), binary_operator>);
75+
7176
STATIC_REQUIRE(is_specialization_of_v<decltype(expression + 42), binary_operator>);
7277
STATIC_REQUIRE(is_specialization_of_v<decltype(42 + expression), binary_operator>);
7378
STATIC_REQUIRE(is_specialization_of_v<decltype(expression + expression), binary_operator>);

0 commit comments

Comments
 (0)