[英]Unintuitive behavior of overloaded explicit constructors
以下代碼使用(本機 64 位)g++-10 在 64 位 Linux 系統上編譯無警告:
#include <cstdint>
class A {
public:
explicit A(unsigned long long int x) { };
explicit A(uint64_t x) { };
};
int main() {}
但是,在 32 位系統上(相同的 Linux 發行版,相同的版本,但它是 32 位機器),我收到此錯誤:
t.cc:6:14: error: ‘A::A(uint64_t)’ cannot be overloaded with ‘A::A(long long unsigned int)’
6 | explicit A(uint64_t x) { };
| ^
t.cc:5:14: note: previous declaration ‘A::A(long long unsigned int)’
5 | explicit A(unsigned long long int x) { };
我通過實驗測試了位大小(printf-ing sizeof(long long unsigned int)
),是的,它們在 32 位和 64 位系統上都是 8 字節長。
為什么它不能在 32 位系統上編譯?
擴大:
我為此尋找了一點,我在 glibc 頭文件/usr/include/x86_64-linux-gnu/bits/types.h
(或/usr/include/i386-linux/bits/types.h
)中發現他們的定義因__extension__
宏或屬性而異:
#if __WORDSIZE == 64
typedef signed long int __int64_t;
typedef unsigned long int __uint64_t;
#else
__extension__ typedef signed long long int __int64_t;
__extension__ typedef unsigned long long int __uint64_t;
#endif
我認為這個__extension__
很重要。 如果__WORDSIZE == 64
,因此我們處於 64 位環境中,那么這些類型是兼容的。 如果不是,那么類型定義會因__extension__
不同。 這個屬性(宏)來自哪里? 如何制作公平的平台無關代碼?
uint64_t
不是基本類型。 它是一個可選的“類型”,是 64 位寬的無符號 integer 類型的別名。 在您的 32 位系統上,這意味着他們很可能將其定義為
using uint64_t = unsigned long long int;
所以它們是相同的類型,你不能有兩個具有相同簽名的重載
在您的 64 位機器上,他們很可能使用unsigned long int
代替,因為這是 64 位 linux 發行版上的 64 位。 這就是為什么它適用於 64 位而不是 32 位的原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.