Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to automatically add literal definitions, based on a single user-defined literal?

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?

like image 935
Rody Oldenhuis Avatar asked Mar 04 '13 07:03

Rody Oldenhuis


People also ask

What is a literal explain any three literals with an example?

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.

What is user defined literal operator in C++?

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.


1 Answers

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");
}
like image 155
Andy Prowl Avatar answered Sep 18 '22 22:09

Andy Prowl