C++11
offers user-defined literals. I've just started to play around with them, which made me wonder whether it would be possible to automatically add all SI multipliers to a single literal I define?
For example, if I define
Length operator "" _m(long double m) {
return Length(m); // Length in meters
}
where Length
is a subclass of some Units
base class, I would like to have a mechanism to automatically add (in the same spirit as boost operators) SI multipliers for all literals that return a Length
:
// these are added automatically when defining the literal "_m":
// Length in:
Length operator "" _Ym(long double Ym); // Yottameters
Length operator "" _Zm(long double Zm); // Zetameters
... // ...
... // ...
Length operator "" _km(long double km); // kilometers
Length operator "" _mm(long double mm); // millimeters
... // ...
... // ...
Length operator "" _zm(long double zm); // zeptometers
Length operator "" _ym(long double ym); // yoctometers
As far as I could see, aside from perhaps some macro magic, there is no way to do this automatically since all user-defined literals need an explicit definition.
..or am I overlooking something?
Literals are the constant values assigned to the constant variables. We can say that the literals represent the fixed values that cannot be modified. It also contains memory but does not have references as variables. For example, const int =10; is a constant integer expression in which 10 is an integer literal.
User Defined Literals in C++ A literal could be anything in a code like a, b, c2. , 'ACB', etc. Similarly, User-Defined Literals (UDL) provides literals for a variety of built-in types that are limited to integer, character, floating-point, string, boolean, and pointer. In simple terms, they combine values with units.
I do not think there is a way to do exactly what you are asking for without "bizarre macros". This is as far as I could get:
template<typename T, T (*op)(long double)>
struct SI
{
// ...
constexpr static T micro = op (.000001);
constexpr static T milli = op (.001);
constexpr static T kilo = op (1000);
constexpr static T mega = op (1000000);
// ...
};
struct Length
{
constexpr Length(long double d) : _d(d) { }
constexpr operator long double() { return _d; }
long double _d;
};
constexpr Length operator "" _m(long double m) {
return Length(m);
}
typedef SI<Length, ::operator "" _m> SI_Length;
int main()
{
constexpr Length l = 3 * SI_Length::kilo;
static_assert(l == 3000, "error");
}
If bizarre macros are allowed, then something like the following should do the job:
#define DEFINE_SI_MULTIPLIERS(T, unit) \
constexpr T operator "" _u ## unit(long double m) \
{ return ::operator "" _ ## unit(0.000001 * m); } \
constexpr T operator "" _m ## unit(long double m) \
{ return ::operator "" _ ## unit(0.001 * m); } \
constexpr T operator "" _k ## unit(long double m) \
{ return ::operator "" _ ## unit(1000 * m); } \
// ...
DEFINE_SI_MULTIPLIERS(Length, m)
int main()
{
constexpr Length l = 3.0_km;
static_assert(l == 3000, "error");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With