-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathradixLiteral.h
80 lines (66 loc) · 3.96 KB
/
radixLiteral.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// Implementation of user-defined literals for different base number literals
#include<type_traits> // for enable_if, TODO: Any other option to disambiguate the template function call?
//#define _b(numeral_system)
#define OPERATOR_LITERAL(numeral_system) \
template<char... chars> \
constexpr int operator"" _b##numeral_system() \
{ \
return bHelper<(numeral_system), chars...>(); \
}
// TODO: Macros for enabling specific features if compiled with different versions of C++ standard
// TODO: Iterative version (can work for C++14 and beyond)
// Use cases:
// 231_b4 -> operator""_b4<2, 3, 1>() -> 2*4^2 + 3*4^1 + 1*4^0
// 254_b6 -> operator""_b6<2, 5, 4>()
// 457_b7 -> operator""_b7<4, 5, 7>() -> should cause static_assert or some safety mechanism, not SFINAE
// Define every of 0-9 numeric system implementations of just enable if it is used?
// This could be guarded by additional #define which could decide what range of available numeric systems should
// be generated by the preprocessor. Do it with a macro loop? Or switch case? Or it could be somehow be driven by the usage of the literal?
// Taking template parameter pack of non-type template arguments of type char
// Variadic tamplate needed probably only for C++11 standard to assign meaning for the values of digits (because of no loops, no 'if' statements, but recursion possible etc.)
// No non-constexpr version needed, user-defined literals were introduced in C++11, the same standard as for constexpr
// TODO: Any macro magic to change the _b3 to, for example, _b6 in case of senary based system?
// Need to just replace the hardcoded number in literal suffix and implementation
// Introduce macro for literal replacing and second template argument for the numeric system?
// Introduce the least amount of macro substitution - only in operator""() implementation?
template<typename Data> // TODO: Artificial constrains on the types that this template could be instantiated with?
constexpr Data pow(Data arg, int power)
{
// Only arithmetic types possible - how to deal with possible conversions and so on? How to deal with returning 1.0?
// Could be done in one template or template partial specialization would be needed?
return power == 0 ? 1.0 : arg * pow(arg, power - 1); // TODO: Swap the actual calculations with base case for more efficiency? Mark calc more likely?
}
// TODO: Ambiguous call in case of one template parameter - disambiguation presently done with enable_if(tail > 0)
// Base case for variadic template - a helper function
template<unsigned base, char c>
constexpr int bHelper() // No function to match in case of ambiguous call without enable_if
{
// TODO: static_assert or other kind of check
return (c - '0'); // TODO: Conversion from char to int is needed to give meaningful result? Or ASCII cares about it? Can this be instantiated with modified char template argment on the caller side?
}
template<unsigned base, char c, char... tail>
std::enable_if<(sizeof...(tail) > 0), int>::type // TODO: Will that return a constexpr qualified int 'constexpr int'?
//constexpr int
bHelper()
{
// TODO: Assert or other check
return ((c - '0') * pow(base, sizeof...(tail))) + bHelper<base, tail...>(); // TODO: (c-'0') would get the actual int representation
}
// TODO: Generalize with a macro printing a proper version of this function and introduce additional
// template parameter substituted with the macro arg?
//template<char... chars> // At this point it should be a macro
//constexpr int operator"" _b3()
//{
// return bHelper<chars...>();
//}
// TODO: Remove and/or move to the client application code
// TODO: Workaround for enabling of non-declarative usage -
// automatic generation of literal implementation in case of usage of _b(x) is "detected"
//OPERATOR_LITERAL(3);
//OPERATOR_LITERAL(5);
//#define OPERATOR_LITERAL(numeral_system) \
// template<char... chars> \
// constexpr int operator"" _b##numeral_system() \
// { \
// return bHelper<chars..., (numeral_system)>(); \
// }