I am working with a third party library which provides a Numeric
class that must be templated with precision and scale arguments. Unfortunately, within the context of the library I am creating, the precision and scale is not known until runtime, so I need to create a runtime mapping of those values to their respective templated functions.
The Numeric library supports up to 38 decimal digits, so in theory I need to create a mapping of the form:
mapping = {
<38, 38>: []() { // do something with Numeric<38, 38> ... },
<38, 37>: []() { // do something with Numeric<38, 37> ... },
...
<37, 37>: []() { // do something with Numeric<38, 37> ... },
<37, 36>: []() { // do something with Numeric<38, 37> ... },
...
}
For all precision and scale arguments in the range (0, 38], where scale <= precision
This is the code I’ve created, ignoring the implementation of the std::function map values and using a smaller parameter pack for now:
using funcMapType = std::map<std::pair<int, int>, std::function<void(void)>>;
template <int P, int S, int... Rest> struct NumericCreatorInserter {
static void insert(funcMapType &func_map) {
NumericCreatorInserter<P, P>::insert(func_map);
NumericCreatorInserter<P, S>::insert(func_map);
NumericCreatorInserter<P, Rest...>::insert(func_map);
NumericCreatorInserter<S, Rest...>::insert(func_map);
}
};
template <int Precision, int Scale>
struct NumericCreatorInserter<Precision, Scale> {
static void insert(funcMapType &func_map) {
std::cout << "Precision is: " << Precision << " and scale is: " << Scale
<< std::endl;
func_map.emplace(std::make_pair(Precision, Scale), [](void) { return; });
}
};
static funcMapType initializeNumericCreatorMap() {
funcMapType numeric_creators;
NumericCreatorInserter<3, 2, 1, 0>::insert(numeric_creators);
return numeric_creators;
};
Debugging this at runtime, I get the following:
Precision is: 3 and scale is: 3
Precision is: 3 and scale is: 2
Precision is: 3 and scale is: 3
Precision is: 3 and scale is: 1
Precision is: 3 and scale is: 0
Precision is: 1 and scale is: 0
Precision is: 2 and scale is: 2
Precision is: 2 and scale is: 1
Precision is: 2 and scale is: 0
Precision is: 1 and scale is: 0
I am expecting to see pairs of (3, 3), (3, 2), (3, 1), (3, 0), (2, 2), (2, 1), etc…
I think I understand the issue with my code – the sequence starting with (3, 3), (3, 1), (3, 0), and (1, 0) happens when P = 3, S = 1, and Rest…=0, which occurs during the first recursive invocation of the function
With that said, I am struggling with how to express what I am trying to achieve in C++. Is there another template specialization I should be introducing to get this to work?
Ideally I am looking for a solution that works with C++17