當我使用特定的數據類型時,通常需要知道它在程序中佔用的大小。最近我想到了通用解決方案,它將處理C++語言中所有數據類型的這個問題,包括類型別名和用戶定義的數據類型。當我開始實現時,我意識到爲所有平臺編寫可移植程序並不容易,因爲C++中的數據類型實際上是編譯器,體系結構和操作特定的實體。程序在C++中顯示所有基本類型的數據大小
它主要是工作,但有一些邊緣案例我不能處理和夫妻關係,我不知道。
方案的簡要說明:
該程序使用模板專門 基本數據類型之間進行區分。操作是編譯時和決策機制 通過模板專業化工作。問題是如果兩種類型被推斷爲包括類型別名的相同類型,那麼碰巧存在編譯器錯誤。
簡單例子是:
「短」或「短整型」或「符號的短」可以是所有等同於「短整型」所感知由編譯器(當然這可以確實編譯器特定的特徵)。如果程序都提供了「short」和「short int」,模板專門化機制會抱怨已經定義了一個。
所以,問題是:
我怎樣才能確保,例如,無論是類型「短」,「短整型」或「符號短」會被推斷爲同一類型或不?有沒有辦法在編譯時檢查?
類型別名的情況也是如此,因爲模板特化是通過它們的原始類型發生的。同樣,如果同時提供「short int」和「std :: size_t」,並且如果系統定義「std :: size_t」爲「short int」,程序將不編譯,因爲編譯器會抱怨存在已經有一個專門的模板。
我已經使用以下link來確定哪些類型相互等價,但我懷疑實現規則可能不會被所有編譯器遵循。
我得到的輸出。
bool : 1 bytes | 8 bits
char : 1 bytes | 8 bits
signed char : 1 bytes | 8 bits
unsigned char : 1 bytes | 8 bits
wchar_t : 4 bytes | 32 bits
char16_t : 2 bytes | 16 bits
char32_t : 4 bytes | 32 bits
short int : 2 bytes | 16 bits
unsigned short int : 2 bytes | 16 bits
int : 4 bytes | 32 bits
unsigned int : 4 bytes | 32 bits
long int : 8 bytes | 64 bits
unsigned long int : 8 bytes | 64 bits
long long int : 8 bytes | 64 bits
unsigned long long int : 8 bytes | 64 bits
float : 4 bytes | 32 bits
double : 8 bytes | 64 bits
long double : 16 bytes | 128 bits
nullptr_t : 8 bytes | 64 bits
Example : 168 bytes | 1344 bits
NULL macro is of integral type.
這在概念上我所需要的:
bool : 1 bytes | 8 bits
char : 1 bytes | 8 bits
signed char : 1 bytes | 8 bits
unsigned char : 1 bytes | 8 bits
wchar_t : 4 bytes | 32 bits
char16_t : 2 bytes | 16 bits
char32_t : 4 bytes | 32 bits
short int : 2 bytes | 16 bits
// -----------WHAT I NEED CONCEPTUALLY----------------
short : short is same as short int //This would be a compile-time error normally.
signed short int : signed short int is same as short int //This would also be a compiler time error.
std::size_t : std::size_t is of short int type. //Since "short int" is already defined, this is compile-time error as well.
//-----------------------------------------------------
unsigned short int : 2 bytes | 16 bits
int : 4 bytes | 32 bits
unsigned int : 4 bytes | 32 bits
long int : 8 bytes | 64 bits
unsigned long int : 8 bytes | 64 bits
long long int : 8 bytes | 64 bits
unsigned long long int : 8 bytes | 64 bits
float : 4 bytes | 32 bits
double : 8 bytes | 64 bits
long double : 16 bytes | 128 bits
nullptr_t : 8 bytes | 64 bits
Example : 168 bytes | 1344 bits
NULL macro is of integral type.
這裏是代碼。
#ifndef TYPE_INFO_CPP
#define TYPE_INFO_CPP
#include <iostream>
#include <iomanip>
#include <type_traits>
/*
Just call:
SYS_CHECK();
In your main function
*/
//Types given into the template function as template parameters via macro
#define TYPES bool, \
char, \
signed char, \
unsigned char, \
wchar_t, \
char16_t, \
char32_t, \
short int, \
unsigned short int, \
int, \
unsigned int, \
long int, \
unsigned long int, \
long long int, \
unsigned long long int, \
float, \
double, \
long double, \
std::nullptr_t, \
Example
// std::size_t, \
// std::string::size_type
//Dummy Struct Declaration to enable Template Specialization
template <typename T>
struct TypeTraits;
//Template Specialization via macro
//Template Specialization is used to distinguish different types
#define REGISTER_TYPE(X) \
template <> \
struct TypeTraits <X> { \
static const char * name; \
}; \
const char * TypeTraits<X>::name = #X;
//To get rid of std:: prefix during console output
#define INTRODUCE_NULLPTR_T() \
using std::nullptr_t;
//Example User-Defined Type Body
struct Example {
char arr1[100];
int a;
double b;
char arr2[50];
};
//These macros are short-hand for declaring specialized templates of the dummy template declared above
REGISTER_TYPE(bool)
REGISTER_TYPE(char)
REGISTER_TYPE(signed char)
REGISTER_TYPE(unsigned char)
REGISTER_TYPE(wchar_t)
REGISTER_TYPE(char16_t)
REGISTER_TYPE(char32_t)
REGISTER_TYPE(short int)
REGISTER_TYPE(unsigned short int)
REGISTER_TYPE(int)
REGISTER_TYPE(unsigned int)
REGISTER_TYPE(long int)
REGISTER_TYPE(unsigned long int)
REGISTER_TYPE(long long int)
REGISTER_TYPE(unsigned long long int)
REGISTER_TYPE(float)
REGISTER_TYPE(double)
REGISTER_TYPE(long double)
//Example User-Defined Type
REGISTER_TYPE(Example)
INTRODUCE_NULLPTR_T()
REGISTER_TYPE(nullptr_t)
template <bool T = std::is_integral<decltype(NULL)>::value,
bool U = std::is_pointer<decltype(NULL)>::value,
bool Y = std::is_scalar<decltype(NULL)>::value>
void is_NULL_integral() {
std::cout << "NULL macro is of ";
if (T) {
std::cout << "integral";
}
else if (U) {
std::cout << "pointer";
}
else if(Y) {
std::cout << "nulltpr_t";
}
else {
std::cout << "neither pointer nor integral or scalar";
}
std::cout << " type." << std::endl;
}
template <typename T, short int byte = 8>
void convert_byte_to_bit() {
std::cout << " | ";
std::cout << byte * sizeof(T) << " bits" << std::endl;
}
template <typename T>
void _display_helper() {
std::cout << std::left << std::setw(23) << TypeTraits<T>::name << " : "
<< sizeof(T) << " bytes" << std::left;
convert_byte_to_bit<T>();
}
template <typename T>
void display_default_size() {
_display_helper<T>();
}
template <typename T, typename U, typename ... Args>
void display_default_size() {
_display_helper<T>();
display_default_size<U, Args...>();
}
void SYS_CHECK() {
display_default_size<TYPES>();
std::cout << std::endl;
is_NULL_integral();
}
#endif
你有沒有試過諮詢'限制'頭文件? –
我應該在那裏找到什麼信息? – ugar