为什么 `uint64_t` 的模板特化与 Mac 平台上的 `unsigned long` 不匹配?

Why this template specialization for `uint64_t` doesn't match with `unsigned long` on Mac platform?

为什么以下代码片段在 Mac 平台上使用 clang++ 编译失败? 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: error: variable type 'Serializer' is an abstract class

Serializer<unsigned long> s;

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

pure virtual method 'ToString' in 'Serializer'

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;
}

正如所讨论的那样,通过使用 compile-time-error-method,发现 uint64_t 的类型是 unsigned long long 而不是 unsigned long。大小相同,但它们的 names 不同,众所周知,编译器对 names 高度敏感和严格,这是正确的!

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

介于两者之间 headers 添加如下内容:

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...){}
};

祝你好运!