不能保證每個平臺都會以同樣的方式定義固定寬度的整數類型,或者它們將根據任何給定平臺上的基本類型進行定義。因此,爲了確保您的重載將捕獲任何給定平臺上的固定寬度類型,您需要確定它們在該平臺上的實現方式。
雖然你可以用模板技巧做到這一點,但最簡單的方法是使用一個獨特的最小幫助程序,輸出每個固定寬度和基本類型的typeid
,允許你比較它們的內部名稱以確定每個固定寬度類型如何在該編譯器的該平臺&上實現。
#include <cstdint>
#include <iostream>
#include <iomanip>
#include <typeinfo>
int main() {
std::cout << std::left;
std::cout << std::setw(10) << "int8_t: " << typeid(int8_t).name() << '\n'
<< std::setw(10) << "int16_t: " << typeid(int16_t).name() << '\n'
<< std::setw(10) << "int32_t: " << typeid(int32_t).name() << '\n'
<< std::setw(10) << "int64_t: " << typeid(int64_t).name() << '\n'
<< std::setw(10) << "uint8_t: " << typeid(uint8_t).name() << '\n'
<< std::setw(10) << "uint16_t: " << typeid(uint16_t).name() << '\n'
<< std::setw(10) << "uint32_t: " << typeid(uint32_t).name() << '\n'
<< std::setw(10) << "uint64_t: " << typeid(uint64_t).name() << '\n'
<< std::endl;
std::cout << std::setw(20) << "char: " << typeid(char).name() << '\n'
<< std::setw(20) << "signed char: " << typeid(signed char).name() << '\n'
<< std::setw(20) << "unsigned char: " << typeid(unsigned char).name() << '\n'
<< std::setw(20) << "signed short: " << typeid(signed short).name() << '\n'
<< std::setw(20) << "unsigned short: " << typeid(unsigned short).name() << '\n'
<< std::setw(20) << "signed int: " << typeid(signed int).name() << '\n'
<< std::setw(20) << "unsigned int: " << typeid(unsigned int).name() << '\n'
<< std::setw(20) << "signed long: " << typeid(signed long).name() << '\n'
<< std::setw(20) << "unsigned long: " << typeid(unsigned long).name() << '\n'
<< std::setw(20) << "signed long long: " << typeid(signed long long).name() << '\n'
<< std::setw(20) << "unsigned long long: " << typeid(unsigned long long).name() << '\n'
<< std::endl;
}
輸出示例:
// MSVC 2015 (x86 & x64):
int8_t: signed char
int16_t: short
int32_t: int
int64_t: __int64
uint8_t: unsigned char
uint16_t: unsigned short
uint32_t: unsigned int
uint64_t: unsigned __int64
char: char
signed char: signed char
unsigned char: unsigned char
signed short: short
unsigned short: unsigned short
signed int: int
unsigned int: unsigned int
signed long: long
unsigned long: unsigned long
signed long long: __int64
unsigned long long: unsigned __int64
// Clang & GCC (x64):
int8_t: a
int16_t: s
int32_t: i
int64_t: l
uint8_t: h
uint16_t: t
uint32_t: j
uint64_t: m
char: c
signed char: a
unsigned char: h
signed short: s
unsigned short: t
signed int: i
unsigned int: j
signed long: l
unsigned long: m
signed long long: x
unsigned long long: y
從這:
- MSVC(在x86 & x64的Windows中,因爲ILP32 & LLP64使用相同類型的大小):我們可以看到,固定寬度類型基於基本類型;注意,對於64位整數類型,編譯器將發出內部名稱
__int64
(來自之前long long
是標準化的同義詞,如Bo Persson pointed out in the comments)代替規範名稱long long
- 鏘& GCC(在x64 * nix中):通過比較損壞的類型名稱,我們可以看到:
- 8位類型基於
char
類型。
- 16位類型基於
short
類型。
- 32位類型基於
int
類型。
- 64位類型基於
long
類型。
從這一點,我們知道,在這些平臺上,這些編譯器:
signed char
來抓int8_t
。
unsigned char
將捕獲uint8_t
。
signed short
將捕獲int16_t
。
unsigned short
將捕獲uint16_t
。
- 等等...
- [請注意,由於Windows的LLP64和* nix的LP64模式之間的差異,
int64_t
& uint64_t
將由不同的重載捕獲。]
然後,您可以將此使用您可能希望使用的任何其他平臺和編譯器進行處理,從而允許您檢測何時需要進行特定於平臺的修改。
雖然這看起來像一個XY問題。你的主要問題是,你希望能夠重載固定寬度類型的平臺,他們不同於基本類型,但不知道如何做到這一點,而不會在平臺上破壞你的代碼。與基本類型相同。
要做到這一點,您需要找到一種方法來唯一標識您所在的平臺;最簡單的方法是looking for macros specific to that platform。
void func( char);
void func( signed char);
void func(unsigned char);
void func( short);
void func(unsigned short);
// ...
#ifdef PLATFORM_WHERE_INT8_T_ISNT_SIGNED_CHAR
void func(int8_t);
void func(uint8_t);
#endif
#ifdef PLATFORM_WHERE_INT16_T_ISNT_SIGNED_SHORT
void func(int16_t);
void func(uint16_t);
#endif
// ...
使用像這樣的設置,您可以定義附加重載,其中固定寬度的類型不是基本類型的平臺,而不會影響他們是基本類型的平臺。這可以讓你做任何平臺特定的處理,然後把它們交給你的基本類型過載之一(如果有必要的話)。
您可以將int8_t類型的函數定義爲刪除。 –
而不是說「全部」,你可以產生一個明確的清單,你是什麼超載? (說「每一個的」簽名「和」未簽名「:將它減半是可以的)。因爲你所說的「全部」可能不是「全部」。 – Yakk
取決於你對「接受」的定義。你可以將'int8_t'傳遞給一個定義爲接受'int'的函數,它會接受它。 – melpomene