2016-12-11 3 views
0

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 
+0

Haben Sie versucht, 'limits' Header-Datei zu konsultieren? –

+0

Welche Informationen soll ich dort finden? – ugar

Antwort

1

Wie kann ich sicherstellen, dass, 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?

Sie haben Ihre Frage markiert C++ 11 so ... es ist eine Arbeit für Typeigenschaften; std::is_same.

Es funktioniert Kompilierzeit.

von Beispiel

#include <type_traits> 
#include <iostream> 

int main() 
{ 
    constexpr bool b1 { std::is_same<short, short int>::value }; 
    constexpr bool b2 { std::is_same<short, signed short int>::value }; 
    constexpr bool b3 { std::is_same<short, unsigned short int>::value }; 

    std::cout << b1 << std::endl; // print 1 
    std::cout << b2 << std::endl; // print 1 
    std::cout << b3 << std::endl; // print 0 
} 

En passant: short und short int sind alias für signed short int

--- EDIT ---

Die OP fragen

Ist dort irgendeine Erwähnung in C++ 11 Standard Welche Zustände "short" und "short int" sind tatsächlich Alias ​​für "signed short int"? Gibt es irgendeine Ressource, die ich für die Suche nach anderen Fundamentaltypen verwenden kann?

Ich weiß nicht, wo der Standard es erwähnt, aber ist ein grundlegender Aspekt, der vom alten C anfängt; Sie haben eine wunderbare (IMHO) Ressource verlinkt; auf der Seite Link, den Sie (this page) Sie

  • , dass „Das Schlüsselwort int weggelassen werden kann, wenn eine der Modifikatoren sind unten aufgeführt verwendet“ lesen können,
  • dass signed „ist die Standardeinstellung, wenn weggelassen“
  • und dass "mit allen Typenspezifizierern jede Bestellung erlaubt ist".

So (durch Beispiel) signed short int, short signed int, short int signed, signed int short, int signed short, int short signed, signed short, short signed und short sind alias für den gleichen Typ.

+0

Gibt es eine Erwähnung in C++ 11 Standard, der besagt, dass "short" und "short int" tatsächlich Alias ​​für "signed short int" sind? Gibt es irgendeine Ressource, die ich für die Suche nach anderen Fundamentaltypen verwenden kann? – ugar

+0

@ugarbd - Antwort verbessert; hoffe das hilft. – max66

Verwandte Themen