簡體   English   中英

構造函數不支持模板函數特化嗎?

[英]Does the constructor not support the specialization of template functions?

我試圖讓我班的構造函數function成為特化模板function,但是編譯失敗。 構造函數不支持模板函數特化嗎? 如果這樣做,我如何將專業化模板 function 添加到我類的構造函數 function 中?

#include <iostream>
#include <vector>
using namespace std;
class Bignum {
private:
    vector<char> vec;
public:
    template <class Type> Bignum(const vector<Type> &num) {
        vec = num;
    }
    template <class Type> Bignum(Type &num) {
        while (num) {
            vec.push_back(num % 10);
            num /= 10;
        }
    }
    template <> Bignum(const string &str) {
        auto __first = str.rbegin();
        auto __last = str.rend();
        for (auto i = __first; i <= __last; ++i) {
            vec.push_back(*i);
        }
    }
    template <class Type> Bignum(const Type *__first, const Type *__last) {
        for (const Type *i = __last; i >= __first; --i) {
            vec.push_back(*i);
        }
    }
    template<> Bignum(char *__first, char *__last) {
        for (char * i = __last; i >= __first; --i) {
            vec.push_back(*i - '0');
        }
    }
    Bignum () {
        
    }
    friend ostream& operator << (ostream &os, const Bignum &num) {
        auto __first = num.vec.rbegin();
        auto __last = num.vec.rend();
        for (auto i = __first; i < __last; ++i) {
            os << (char)(*i + '0') << ' ';
        }
        os << (char)(*__last + '0') << endl;
        return os;
    }
    size_t size() const {
        return vec.size();
    }
    const char & at(const size_t &pos) const {
        return vec.at(vec.size() - pos);
    }
    const char & operator [] (const size_t &pos) {
        return vec.at(pos);
    }
};
int main(int argc, const char * argv[]) {
    
    return 0;
}

我在第 29 行收到一個編譯錯誤,顯示沒有 function 模板匹配 function 模板專業化“Bignum”。

如評論中所述,您只需從不需要成為成員 function 模板的構造函數中刪除模板 <>。

但是,考慮如何以更通用的方式完成您可能追求的目標可能會有所幫助。


您實際上打算如何存儲數據是令人困惑的,因為您的實現做了不同的事情(有些人希望它以“小端”存儲,而其他人希望它以“大端”順序存儲)。 此外,您的某些函數期望數據存儲在 [0, 9] 范圍內,而其他函數似乎期望數據存儲在 ['0', '9'] 范圍內。

然而,這些都與我認為的真正問題無關,這是關於構造函數接口的,所以我假設數據存儲為 ASCII 數字 ['0', '9'] 並按照它們的順序存儲打印為字符串 - 只是為了挑選一些東西。

我還建議您使用特定的強類型Digit作為內部表示,這將消除關於含義的所有歧義。 它還會刪除所有不需要的轉換的更改。


看起來您希望能夠從任何可用於創建 char 向量的內容中創建一個 BigNum。

這個構造函數就是這樣做的。 請注意,我們明確禁止采用單一整數類型,因為您可以從其中一個創建向量,但它似乎不是您想要的,因為您有另一個似乎采用整數的構造函數。

template <
    typename... ArgTs,
    std::enable_if_t<
        std::is_constructible_v<std::vector<char>, ArgTs...> &&
            not ((sizeof...(ArgTs) == 1) && ... && std::is_integral_v<ArgTs>),
        bool> = true>
explicit Bignum(ArgTs && ... args)
: vec(std::forward<ArgTs>(args)...)
{
    // If not using a strong type, should at least assert that the
    // data you get is what you expect.
    assert(vec.size() == std::count_if(
        vec.begin(),
        vec.end(),
        [](unsigned char c){ return std::isdigit(c); }));
}

然后,您可以像這樣采用任何無符號整數類型(我將其限制為無符號,因為它看起來不像您的代碼已准備好處理有符號值)。

template <
    typename T,
    std::enable_if_t<
        std::is_integral_v<T> && std::is_unsigned_v<T>,
        bool> = true>
Bignum(T number)
{
    while (number) {
        vec.push_back((number % 10) + '0');
        number /= 10;
    }
    std::reverse(vec.begin(), vec.end());
}

而且,要接受字符串,您不需要成員 function 模板...

Bignum(std::string_view s)
: Bignum(s.begin(), s.end())
{ }

最后,我鼓勵您熟悉標准算法。 例如,

friend std::ostream & operator << (std::ostream & os, Bignum const & num)
{
    std::copy(num.vec.begin(), num.vec.end(), std::ostream_iterator<char>(os));
    return os;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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