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)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_unsignedstd::is_integral / std::is_floating_pointNote 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";
}
Live example on Ideone.
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.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With