首页 > 解决方案 > 为什么 `uint64_t` 的模板特化与 Mac 平台上的 `unsigned long` 不匹配?

问题描述

为什么使用 clang++ 在 Mac 平台上编译以下代码段失败?sizeof unsigned longanduint64_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;
}

标签: c++templatestypestemplate-specialization

解决方案


正如所讨论的,通过使用 compile-time-error-method,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...){}
};

祝你好运!


推荐阅读