为什么 `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 long
和 uint64_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...){}
};
祝你好运!
为什么以下代码片段在 Mac 平台上使用 clang++ 编译失败?
sizeof
unsigned long
和 uint64_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...){}
};
祝你好运!