I am using a variadic template to construct a key for a map, calculating a number to a base:
template<typename T>
uint64_t key(int base, T n)
{
return uint64_t(n) % base;
}
template<typename T, typename... Args>
uint64_t key(int base, T n, Args... rest)
{
return key(base, rest...) * base + (uint64_t(n) % base);
}
Calling it with key(10, 1, 2, 3)
gives me a key with decimal value 321
. I would prefer to get 123
for the key, and I have found a solution that works:
template<typename T>
uint64_t keyHelper(int& mul, int base, T n)
{
mul = base;
return uint64_t(n) % base;
}
template<typename T, typename... Args>
uint64_t keyHelper(int& mul, int base, T n, Args... rest)
{
int mul_tmp;
uint64_t result = keyHelper(mul_tmp, base, rest...) +
(uint64_t(n) % base) * mul_tmp;
mul = mul_tmp * base;
return result;
}
template<typename... Args>
uint64_t key(int base, Args... args)
{
int mul;
return keyHelper(mul, base, args...);
}
This solution feels like a hack, tho, since it passes around a reference to fix the exponent of multiplications. Is there a simple varidic way where the template calculates the number in the required order, i.e. 123
? I have seen solutions for reversing variadic arguments, and they seem overly complicated.
Since C++17 I would use fold expression (op,...)
to do that:
template<class B, class ... Args>
auto key(B base, Args ... args) {
std::common_type_t<Args...> res{};
( (res *= base, res += args % base), ... );
return res;
}