Matteo
Matteo

Reputation: 8134

How to distinguish a Template Type in C++

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:

Upvotes: 2

Views: 539

Answers (2)

Cory Nelson
Cory Nelson

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

Xeo
Xeo

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";
}

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.

Upvotes: 7

Related Questions