Reputation: 8134
I have a template class, and would like to write a member method that's able to recognize what kind of type the template has been instantiated to.
I need to create a string identifier containing the following information on the type:
The method should return a string composed in the following way:
string: (BIT_DEPTH)-(U|S)-(C|I|F)
BIT_DEPTH -> is the number of bits used to represent type
U | S -> describes if type is signed or unsigned
C | I | F -> describes if type is char int or floating point
I thought of a way to find to bit depth:
int bitDepth = sizeof(TemplateType) * 8;
is it ok?
But have no idea on how to find the other information I need, unless a switch-case
statement like the following is ok (but don't think so):
THE FOLLOWING IS PSEUDO CODE THAT YOU SHOULD HELP ME EXPRESS IN A CORRECT SYNTAX
switch(TemplateType){
case signed: ...;
case unsigned: ...;
default: ...;
}
My questions are two:
switch-case
statement a good idea? (if yes can you please correct the syntax)Upvotes: 2
Views: 539
Reputation: 29981
To add to Xeo's answer, you can remove those warnings by doing this all at compile time with std::enable_if
. For instance:
template<typename T>
inline
typename std::enable_if<std::is_signed<T>::value, char>::type
sign() { return 'S'; }
template<typename T>
inline
typename std::enable_if<std::is_unsigned<T>::value, char>::type
sign() { return 'U'; }
One thing to look out for, though, is that is_signed
for float
is false
!
Upvotes: 2
Reputation: 131789
The bit calculation is OK, but can be improved by using CHAR_BIT
instead of 8
, see this question.
To get the other information, you can use <type_traits>
, specifically:
std::is_signed
/ std::is_unsigned
std::is_integral
/ std::is_floating_point
Note that floating point types are always signed, but std::is_signed
will return false, because it tests if the type is a signed integer.
Also note that char
is just another integral type, so there's no standard type trait to specifically test that, but you can use a simple std::is_same<T, char>
.
In code, this might look like the following:
#include <iostream>
#include <type_traits>
#include <climits> // CHAR_BIT
template<class T>
void f(){
std::cout << sizeof(T) * CHAR_BIT << "-";
if(std::is_integral<T>::value){
if(std::is_signed<T>::value)
std::cout << "S";
else
std::cout << "U";
std::cout << "-";
if(std::is_same<T, char>::value)
std::cout << "C";
else
std::cout << "I";
}else if(std::is_floating_point<T>::value){
std::cout << "S-F";
}
std::cout << "\n";
}
Note that bool
counts as unsigned integer, but that is easily fixed. Also note that the compiler will spew a bunch of warnings regarding "conditional expression is constant", so that can be improved, but this should suffice as a demonstration.
Upvotes: 7