Wenn ich mit einem bestimmten Datentyp arbeite, muss ich normalerweise die Größe wissen, die es im Programm belegt. Kürzlich dachte ich über eine generische Lösung nach, die dieses Problem für alle Datentypen in C++ - Sprache einschließlich Typaliase und benutzerdefinierter Datentypen behandeln würde.Programm zum Anzeigen von Datengrößen aller grundlegenden Typen in C++
Als ich begann zu implementieren, habe ich festgestellt, dass es nicht wirklich einfach ist, ein tragbares Programm für alle Plattformen zu schreiben, da Datentypen in C++ wirklich Compiler, Architektur und betriebspezifische Entitäten sind.
Es funktioniert meistens, aber es gibt einige Edge-Cases, die ich nicht verarbeiten kann und Punkte koppeln, über die ich nicht sicher bin.
Kurzbeschreibung des Programms:
Das Programm verwendet Template Spezialisierung zwischen grundlegenden Datentypen zu unterscheiden. Operationen sind Kompilierungszeit und Entscheidungsmechanismus Arbeit über Vorlagenspezialisierung. Problem damit ist, wenn zwei Typen auf den gleichen Typ einschließlich Typ-Aliase abgeleitet werden, ist es ein Compiler-Fehler (s).
Ein kurzes Beispiel:
„kurz“ oder „short int“ oder „unterzeichnet kurz“ können alle äquivalent zu „short int“, wie er durch den Compiler wahrgenommen (natürlich kann das wirklich sein Compiler spezifische Merkmal). Wenn "short" und "short int" beide dem Programm zur Verfügung gestellt werden, beschwert sich der Vorlagenspezialisierungsmechanismus, dass einer bereits definiert ist.
Die Frage ist also:
Wie kann ich sicher stellen, zum Beispiel, ob Typen „short“, „short int“ oder „unterzeichnete kurz“ werden auf die gleiche Art oder nicht abgeleitet werden? Gibt es eine Möglichkeit, dies bei der Kompilierung zu überprüfen?
Die Situation ist gleich für Typ-Aliase, da die Vorlagenspezialisierung über ihren ursprünglichen Typ erfolgt. Wenn sowohl "short int" als auch "std :: size_t" bereitgestellt werden und wenn "std :: size_t" zufällig vom System als "short int" definiert wird, kompiliert das Programm nicht, weil der Compiler beschwert, dass dies der Fall ist eine spezielle Vorlage für eine bereits.
Ich habe folgende link verwendet, um sicherzustellen, welche Typen einander gleich sind, aber ich vermute, dass die Regeln möglicherweise nicht von allen Compilern befolgt werden.
Der Ausgang, den ich bekomme.
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.
Dies ist vom Konzept her, was ich brauche:
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.
Hier ist der Code ist.
#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
Haben Sie versucht, 'limits' Header-Datei zu konsultieren? –
Welche Informationen soll ich dort finden? – ugar