Skip to content

Commit e13aecb

Browse files
committed
add implicit Number-Double conversions
1 parent 3e36e31 commit e13aecb

File tree

2 files changed

+50
-168
lines changed

2 files changed

+50
-168
lines changed

include/units/units.hpp

Lines changed: 46 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include <type_traits>
1010
#include <utility>
1111

12-
1312
// define M_PI if not already defined
1413
#ifndef M_PI
1514
#define M_PI 3.14159265358979323846
@@ -56,6 +55,15 @@ class Quantity {
5655
Luminosity,
5756
Moles>;
5857

58+
using Dimensionless = Quantity<std::ratio<0>,
59+
std::ratio<0>,
60+
std::ratio<0>,
61+
std::ratio<0>,
62+
std::ratio<0>,
63+
std::ratio<0>,
64+
std::ratio<0>,
65+
std::ratio<0>>;
66+
5967
/**
6068
* @brief construct a new Quantity object
6169
*
@@ -70,8 +78,19 @@ class Quantity {
7078
* @param value the value to initialize the quantity with
7179
*/
7280
explicit constexpr Quantity(double value)
81+
requires(!std::is_same_v<Self, Dimensionless>)
7382
: value(value) {}
7483

84+
constexpr Quantity(double value)
85+
requires std::is_same_v<Self, Dimensionless>
86+
: value(value) {}
87+
88+
constexpr operator double()
89+
requires std::is_same_v<Self, Dimensionless>
90+
{
91+
return value;
92+
}
93+
7594
/**
7695
* @brief construct a new Quantity object
7796
*
@@ -104,6 +123,12 @@ class Quantity {
104123
value += other.value;
105124
}
106125

126+
constexpr void operator+=(double other)
127+
requires std::is_same_v<Self, Dimensionless>
128+
{
129+
value += other;
130+
}
131+
107132
/**
108133
* @brief set the value of this quantity to its current value minus another
109134
* quantity
@@ -114,6 +139,12 @@ class Quantity {
114139
value -= other.value;
115140
}
116141

142+
constexpr void operator-=(double other)
143+
requires std::is_same_v<Self, Dimensionless>
144+
{
145+
value -= other;
146+
}
147+
117148
/**
118149
* @brief set the value of this quantity to its current value times a double
119150
*
@@ -123,6 +154,12 @@ class Quantity {
123154
value *= multiple;
124155
}
125156

157+
constexpr void operator*=(double other)
158+
requires std::is_same_v<Self, Dimensionless>
159+
{
160+
value *= other;
161+
}
162+
126163
/**
127164
* @brief set the value of this quantity to its current value divided by a
128165
* double
@@ -133,6 +170,12 @@ class Quantity {
133170
value /= dividend;
134171
}
135172

173+
constexpr void operator/=(double other)
174+
requires std::is_same_v<Self, Dimensionless>
175+
{
176+
value /= other;
177+
}
178+
136179
/**
137180
* @brief set the value of this quantity to a double, only if the quantity
138181
* is a number
@@ -165,33 +208,15 @@ class Number : public Quantity<std::ratio<0>,
165208
std::ratio<0>,
166209
std::ratio<0>> {
167210
public:
168-
template<typename T>
169-
constexpr Number(T value)
211+
constexpr Number(double number)
170212
: Quantity<std::ratio<0>,
171213
std::ratio<0>,
172214
std::ratio<0>,
173215
std::ratio<0>,
174216
std::ratio<0>,
175217
std::ratio<0>,
176218
std::ratio<0>,
177-
std::ratio<0>>(double(value)) {}
178-
179-
constexpr Number(Quantity<std::ratio<0>,
180-
std::ratio<0>,
181-
std::ratio<0>,
182-
std::ratio<0>,
183-
std::ratio<0>,
184-
std::ratio<0>,
185-
std::ratio<0>,
186-
std::ratio<0>> value)
187-
: Quantity<std::ratio<0>,
188-
std::ratio<0>,
189-
std::ratio<0>,
190-
std::ratio<0>,
191-
std::ratio<0>,
192-
std::ratio<0>,
193-
std::ratio<0>,
194-
std::ratio<0>>(value) {};
219+
std::ratio<0>>(number) {}
195220
};
196221

197222
template<typename Q>
@@ -591,124 +616,6 @@ struct LookupName<Quantity<std::ratio<0>,
591616
using Named = Number;
592617
};
593618

594-
[[maybe_unused]]
595-
constexpr Number num = Number(1.0);
596-
597-
constexpr Number operator""_num(long double value) {
598-
return Number(Quantity<std::ratio<0>,
599-
std::ratio<0>,
600-
std::ratio<0>,
601-
std::ratio<0>,
602-
std::ratio<0>,
603-
std::ratio<0>,
604-
std::ratio<0>,
605-
std::ratio<0>>(static_cast<double>(value)));
606-
}
607-
608-
constexpr Number operator""_num(unsigned long long value) {
609-
return Number(Quantity<std::ratio<0>,
610-
std::ratio<0>,
611-
std::ratio<0>,
612-
std::ratio<0>,
613-
std::ratio<0>,
614-
std::ratio<0>,
615-
std::ratio<0>,
616-
std::ratio<0>>(static_cast<double>(value)));
617-
}
618-
619-
template<>
620-
struct std::formatter<Number> : std::formatter<double> {
621-
auto format(const Number& number, std::format_context& ctx) const {
622-
return std::formatter<double>::format(number.internal(), ctx);
623-
}
624-
};
625-
626-
inline std::ostream& operator<<(std::ostream& os, const Number& quantity) {
627-
os << quantity.internal() << " " << num;
628-
return os;
629-
}
630-
631-
inline constexpr Number from_num(double value) {
632-
return Number(value);
633-
}
634-
635-
inline constexpr double to_num(Number quantity) {
636-
return quantity.internal();
637-
}
638-
639-
#define NEW_NUM_TO_DOUBLE_COMPARISON(op) \
640-
constexpr bool operator op(Number lhs, double rhs) { \
641-
return (lhs.internal() op rhs); \
642-
} \
643-
constexpr bool operator op(double lhs, Number rhs) { \
644-
return (lhs op rhs.internal()); \
645-
}
646-
647-
namespace units_double_ops {
648-
NEW_NUM_TO_DOUBLE_COMPARISON(==)
649-
NEW_NUM_TO_DOUBLE_COMPARISON(!=)
650-
NEW_NUM_TO_DOUBLE_COMPARISON(<=)
651-
NEW_NUM_TO_DOUBLE_COMPARISON(>=)
652-
NEW_NUM_TO_DOUBLE_COMPARISON(<)
653-
NEW_NUM_TO_DOUBLE_COMPARISON(>)
654-
} // namespace units_double_ops
655-
656-
#define NEW_NUM_AND_DOUBLE_OPERATION(op) \
657-
constexpr Number operator op(Number lhs, double rhs) { \
658-
return (lhs.internal() op rhs); \
659-
} \
660-
constexpr Number operator op(double lhs, Number rhs) { \
661-
return (lhs op rhs.internal()); \
662-
}
663-
664-
namespace units_double_ops {
665-
NEW_NUM_AND_DOUBLE_OPERATION(+)
666-
NEW_NUM_AND_DOUBLE_OPERATION(-)
667-
NEW_NUM_AND_DOUBLE_OPERATION(*)
668-
NEW_NUM_AND_DOUBLE_OPERATION(/)
669-
} // namespace units_double_ops
670-
671-
#define NEW_NUM_AND_DOUBLE_ASSIGNMENT(op) \
672-
constexpr void operator op##=(Number& lhs, double rhs) { \
673-
lhs = lhs.internal() op rhs; \
674-
} \
675-
constexpr void operator op##=(double& lhs, Number rhs) { \
676-
lhs = lhs op rhs.internal(); \
677-
}
678-
679-
namespace units_double_ops {
680-
NEW_NUM_AND_DOUBLE_ASSIGNMENT(+)
681-
NEW_NUM_AND_DOUBLE_ASSIGNMENT(-)
682-
NEW_NUM_AND_DOUBLE_ASSIGNMENT(*)
683-
NEW_NUM_AND_DOUBLE_ASSIGNMENT(/)
684-
} // namespace units_double_ops
685-
686-
namespace units_double_ops {
687-
constexpr Number& operator++(Number& lhs, int) {
688-
lhs += 1;
689-
return lhs;
690-
}
691-
692-
constexpr Number operator++(Number& lhs) {
693-
Number copy = lhs;
694-
lhs += 1;
695-
return copy;
696-
}
697-
698-
constexpr Number& operator--(Number& lhs, int) {
699-
lhs -= 1;
700-
return lhs;
701-
}
702-
703-
constexpr Number operator--(Number& lhs) {
704-
Number copy = lhs;
705-
lhs -= 1;
706-
return copy;
707-
}
708-
} // namespace units_double_ops
709-
710-
NEW_UNIT_LITERAL(Number, percent, num / 100)
711-
712619
NEW_UNIT(Mass, kg, 1, 0, 0, 0, 0, 0, 0, 0)
713620
NEW_UNIT_LITERAL(Mass, g, kg / 1000)
714621
NEW_UNIT_LITERAL(Mass, lb, g * 453.6)

src/main.cpp

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ void initialize() {
2323
std::cout << std::format("{:.2f}", a) << std::endl;
2424
units::Vector2D<Length> v2a = units::V2Position(2_in, 2_in) / 2;
2525
std::cout << std::format("{}", v2a) << std::endl;
26-
units::max(2, 2_num);
27-
auto ab = 2_in;
28-
ab *= 2_num;
26+
units::max(2, 2);
27+
Length ab = 2_in;
28+
ab *= a;
2929
}
3030

3131
constexpr void miscTests() {
@@ -108,35 +108,10 @@ constexpr void angleRangeTests() {
108108
}
109109

110110
constexpr Number numAssignmentTests() {
111-
using namespace units_double_ops;
112-
Number n = 1_num; // 1
111+
Number n = 1; // 1
113112
n += 2; // 3
114-
n--; // 2
115113
n -= 3; // -1
116114
n *= 2; // -2
117115
n /= 2; // -1
118-
n++; // 0
119116
return n;
120117
}
121-
122-
constexpr double doubleAssignmentTests() {
123-
using namespace units_double_ops;
124-
double d = 1; // 1
125-
d += 2_num; // 3
126-
d -= 2_num; // 1
127-
d *= 2_num; // 2
128-
d /= 2_num; // 1
129-
return d;
130-
}
131-
132-
constexpr void numberOperatorTests() {
133-
using namespace units_double_ops;
134-
static_assert(1_num + 2 == 3);
135-
static_assert(1 + 2_num <= 3);
136-
static_assert(1 / 2_num >= 0);
137-
138-
static_assert(numAssignmentTests() == 0);
139-
static_assert(doubleAssignmentTests() == 1);
140-
}
141-
142-
constexpr void formatTests() {}

0 commit comments

Comments
 (0)