我使用一个可变的模板来构造一个映射的键,计算一个数字到一个基数:
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);
}
用key(10, 1, 2, 3)
调用它会得到一个十进制值321
的键。我更愿意得到123
的关键,我已经找到了一个解决方案,工作:
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...);
}
这个解决方案感觉像是一个hack,但是,因为它传递了一个引用来固定乘法的指数。是否有一个简单的可变方式,模板计算所需的顺序,即123
的数字?我已经看到了反转可变参数的解决方案,它们似乎过于复杂。
从c++ 17开始,我将使用折叠表达式(op,...)
来完成:
template<class B, class ... Args>
auto key(B base, Args ... args) {
std::common_type_t<Args...> res{};
( (res *= base, res += args % base), ... );
return res;
}
演示我已经找到了一个解决方案,感觉稍微好一点,以下是@Andrey Semashev的评论:
template<int n>
uint64_t exp(int base)
{
return base * exp<n - 1>(base);
}
template<>
uint64_t exp<0>(int base)
{
return 1;
}
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...) +
(uint64_t(n) % base) * exp< sizeof...(rest) >(base);
}
这个怎么样:
template<typename T>
uint64_t key_impl(int base, unsigned int exp, T n)
{
return uint64_t(n) % base;
}
template<typename T, typename... Args>
uint64_t key_impl(int base, unsigned int exp, T n, Args... rest)
{
uint64_t res = uint64_t(n) % base;
for (unsigned int i = 0u; i < exp; ++i)
res *= base;
return key_impl(base, exp - 1u, rest...) + res;
}
template<typename... Args>
uint64_t key(int base, Args... args)
{
return key_impl(base, sizeof...(Args) - 1u, args...);
}
由于参数的数量是已知的,所以最大指数是已知的,您可以使用它来计算总和
template<typename T, typename... Args>
uint64_t key(int base, T n, Args... rest)
{
return (uint64_t(n) % base) * std::pow(base, sizeof...(rest))
+ key(base, rest...);
}
(基本大小写不变)
演示注意,你不应该在这里使用std::pow
;写一个整数求幂的函数。