为什么在Mac平台上,此uint64_t模板专用化与`unsigned long`不匹配?

时间:2019-05-20 04:22:01

标签: c++ templates types template-specialization

为什么以下代码片段在使用clang ++的Mac平台上编译失败? sizeof unsigned longuint64_t都是8,所以我认为它们是同一类型。那么,为什么编译器认为Serializer<unsigned long>是抽象的呢?

因为我已经定义了Serializer<uint64_t>, Serializer<int64_t>, Serializer<uint32_t>, Serializer<int32_t>, Serializer<uint16_t>, Serializer<int16_t>, Serializer<uint8_t>, Serializer<int8_t>,有什么方法可以解决此问题并避免定义更多的类型,例如Serializer<unsigned long>

以下是错误消息,clang ++和g ++都给出类似的结果:

  

example.cpp:23:31:错误:变量类型为'Serializer'为   抽象类

Serializer<unsigned long> s;

                          ^ example.cpp:6:25: note: unimplemented 
     

'Serializer'中的纯虚拟方法'ToString'

virtual std::string ToString(const T* val) = 0;

                    ^ 1 error generated.
#include <iostream>
#include <vector>
#include <algorithm>
template <typename T>
class Serializer {
    virtual std::string ToString(const T* val) = 0;
};

template <>
class Serializer<uint64_t> {
public:

    virtual std::string ToString(const int8_t* val) {
        return "";
    }
};

int main(int argc, const char *argv[])
{
    // both of the size is 8 bytes
    std::cout << " size of unsigned long:" << sizeof(unsigned long) << " sizeof uint64_t:" << sizeof(uint64_t);
    // following compile error happen
    Serializer<unsigned long> s;  //<------- Error happen here
    s.ToString(NULL);

    return 0;
}

1 个答案:

答案 0 :(得分:2)

如前所述,通过使用编译时错误方法,发现uint64_t的类型是unsigned long long而不是unsigned long。大小相同,但它们的名称不同,并且众所周知,编译器对名称非常敏感并且严格,所以正确!

可以解决此问题,而无需更改库或更改用户界面!

在标头之间的某些位置添加如下内容:

template <>
class Serializer<unsigned long> : public Serializer<uint64_t>{};

或者如果用户无法访问uint64_t类型,更可能是这种情况:

template <>
class Serializer<unsigned long> : public Serializer<unsigned long long>{};

因此,现在知道unsigned long的专业化与Serializer<uint64_t>的专业化(在某种程度上)相同!

此外,根据Serializer的定义,您可能还需要向其添加一个构造函数,例如:

template <>
class Serializer<unsigned long> : public Serializer<unsigned long long>{
    Serializer(...DATA...):Serializer<unsigned long long>(...DATA...){}
};

如果您不知道定义是什么,这可能会有所帮助:

//for values
class Serializer<unsigned long> : public Serializer<unsigned long long>{
    template<typename ... Ts>
    Serializer(Ts ... Vs):Serializer<unsigned long long>(Vs...){}
};

//for objects
class Serializer<unsigned long> : public Serializer<unsigned long long>{
    template<typename ... Ts>
    Serializer(const Ts& ... Os):Serializer<unsigned long long>(Os...){}
};

祝你好运!