繁体   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