簡體   English   中英

C ++模板特征指定任何無符號整數類型

[英]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>

DEMO

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM