我正在尝试实现一个只接受无符号整数类型的函数。以下是我到目前为止所尝试的内容。它适用于“unsigned int”,但为什么不编译“unsigned short?”
#include <iostream>
#include <type_traits>
template<typename T, class = typename std::enable_if<std::is_unsigned<T>::value>::type>
inline const T oddProduct(T n) noexcept {
return (n <= 1) ? n : (n % 2) ? oddProduct(n - 2)*n : oddProduct(--n);
}
int main() {
std::cout << "Product of odd integers from 1 to 15: " << oddProduct<unsigned short>(15) << std::endl;
return 0;
}
注意:MSVS 2017社区C ++ 14选项。
答案 0 :(得分:3)
问题在于integral promotion:
n - 2
的int
类型不是unsigned
。
您可以尝试添加static_cast
:
template<typename T, class = typename std::enable_if<std::is_unsigned<T>::value>::type>
inline const T oddProduct(T n) noexcept {
return (n <= 1) ? n : (n % 2) ? oddProduct(static_cast<T>(n - 2))*n : oddProduct(--n);
^^^^^^^^^^^^^^
}
所以当您致电n - 2
时,unsigned short
会投放到oddProduct<unsigned short>
。
另一种可能的选择是将2
更改为2U
。
另请注意,一旦您使用 C ++ 14 ,您可以使用std::enable_if_t
:
class = typename std::enable_if_t<std::is_unsigned<T>::value>
答案 1 :(得分:0)
Edgar Rokyan的答案解决了OP代码中的整体推广问题,但是还有另一个问题,即调整返回值类型和可能的计算溢出。
事实上,考虑到问题中提供的示例,&#34;奇数整数从1到15&#34; 的乘积是2027025,这个值需要16以上位(大多数系统中unsigned short
的大小),因此让函数返回相同类型的参数会导致错误的结果。
#include <iostream>
#include <type_traits>
#include <stdexcept>
template<typename T>
inline const auto oddProduct(T n) noexcept
-> std::enable_if_t<std::is_unsigned<T>::value, unsigned long long> {
return n < T{2}
? n
: (n % T{2})
? oddProduct<T>(n - T{2})*n
: oddProduct(--n);
}
template<typename T>
inline const auto oddProduct(T n)
-> std::enable_if_t<std::is_signed<T>::value, unsigned long long> {
if ( n < 0 ) throw std::domain_error("Negative value passed");
return n < T{2}
? n
: (n % T{2})
? oddProduct<std::make_unsigned_t<T>>(n - T{2})*n
: oddProduct<std::make_unsigned_t<T>>(--n);
}
int main() {
unsigned char n0 {15};
std::cout << "Product of odd integers from 1 to 15: " << oddProduct(n0) << '\n';
unsigned short n1 {15};
std::cout << "Product of odd integers from 1 to 15: " << oddProduct(n1) << '\n';
unsigned n2 {15};
std::cout << "Product of odd integers from 1 to 15: " << oddProduct(n2) << '\n';
short n3 {15};
std::cout << "Product of odd integers from 1 to 15: " << oddProduct(n3) << '\n';
}
在我的提案中,该函数始终返回unsigned long long
。我还添加了一个重载来处理签名类型。