Sometimes I need to perform intermediate calculations with double-size values, for example - in this function, which returns a product of two numbers by modulo m
:
template <typename T, typename DT>
T multiply(T x, T y, T mod)
{
return (static_cast<DT>(x % mod) * (y % mod)) % mod;
}
This casting will be necessary if the mod
value is close enough to the maximal value of the type T
. As a result I have to call this function with two template parameters:
z = multiply<int32_t, int64_t>(x, y, m)
This looks ugly, and is error-prone. Is it any way to automatically declare the double-sized type DT
(corresponding to the type T
) inside such a function?
Also I see this document, which is supposed to solve this problem, but I couldn't find any info about its implementation in any popular C compiler.
CodePudding user response:
I might be missing why you want exactly double-sized type, but provided you consider only signed and unsigned integrals, you can just pick the max-size compatible type for the calculations:
template<typename T>
T multiply(T x, T y, T mod) {
static_assert(std::is_integral_v<T>, "Only integral types are expected");
using CT = std::conditional_t<std::is_signed_v<T>, long long,
std::conditional_t<std::is_unsigned_v<T>, unsigned long long, T>>;
return (static_cast<CT>(x % mod) * (y % mod)) % mod;
}