[英]Convert a C++ integral type template parameter to a “longer” integral type
[英]C++ template trait to specify any unsigned integral type
我正在嘗試實現一個只接受無符號整數類型的函數。 以下是我到目前為止所嘗試的內容。 它適用於“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選項。
事情是由於整體推廣 :
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);
^^^^^^^^^^^^^^
}
所以當你調用oddProduct<unsigned short>
時, n - 2
被轉換為unsigned short
。
另一種可能的選擇是將2
改為2U
。
另請注意,一旦使用C ++ 14 ,您可以使用std::enable_if_t
:
class = typename std::enable_if_t<std::is_unsigned<T>::value>
Edgar Rokyan的回答解決了OP代碼中的整體推廣問題,但是還有另一個問題,即調整返回值類型和可能的計算溢出。
事實上,考慮到問題中提供的例子, “從1到15的奇數整數的乘積”是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
。 我還添加了一個重載來處理簽名類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.