3

Suppose I have a type T which is guaranteed to be an array (eg. int[32]). How do I get the type of the elements from the type of the array?

I found a way to do it, but it involves declaring a dummy temporary variable, which I would like to avoid:

#include <iostream>
#include <typeinfo>

using namespace std;

template <typename T>
string getArrayType() {
    // Is there a better way to do this?
    T dummy;
    return typeid(dummy[0]).name();
}

int main() {
    cout << getArrayType<int[1]>() << endl;     // i
    cout << getArrayType<float[1]>() << endl;   // f
}
SlySherZ
  • 1,631
  • 1
  • 16
  • 25

4 Answers4

6

You could use std::remove_all_extents as well

return typeid(typename std::remove_all_extents<T>::type).name();

The documentation for this states

If T is a multidimensional array of some type X, provides the member typedef type equal to X, otherwise type is T.

So it will remove the array type to get at the underlying type contained within that array

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
2
std::remove_all_extents<T>::type

found in the <type_traits> header. And, if your standard library is C++14 rdy

std::remove_all_extents_t<T>
nh_
  • 2,211
  • 14
  • 24
2

If you do not want to create a unnecessary variable you can use std::remove_extent. It will give you the element type of the array type. That would look like

template <typename T>
string getArrayType() {
    return typeid(typename std::remove_extent<T>::type).name();
}
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
2

Suppose I have a type T which is guaranteed to be an array (eg. int[32]). How do I get the type of the elements from the type of the array?

If you use typeid().name(), as in you example, you get the name of the type, not the type.

If you want the type, and use it compile time, and you want it to declare variables, you can define a type traits as follows

template <typename>  
struct typeOfArray
 { };

template <typename T, std::size_t N> 
struct typeOfArray<T[N]>
 { using type = T; };

The following is a full (but c++11) working example

#include <iostream>
#include <type_traits>

template <typename>  
struct typeOfArray
 { };

template <typename T, std::size_t N> 
struct typeOfArray<T[N]>
 { using type = T; };

int main ()
 {
   static_assert( std::is_same<int,
                 typename typeOfArray<int[1]>::type>::value, "!" );

   static_assert( std::is_same<float,
                 typename typeOfArray<float[1]>::type>::value, "!" );

   typename typeOfArray<int[1]>::type i { 42 };

   std::cout << i << std::endl;
 }

If you have to work with c++98, you can't use using, so instead of

using type = T;

you have to use typedef

typedef T type;

The following is a c++98 example (using typeid().name() also)

#include <typeinfo>
#include <iostream>

template <typename>  
struct typeOfArray
 { };

template <typename T, std::size_t N> 
struct typeOfArray<T[N]>
 { typedef T type; };

int main ()
 {
   std::cout << typeid(typeOfArray<int[1]>::type).name() << std::endl;
   std::cout << typeid(typeOfArray<float[1]>::type).name() << std::endl;
 }
max66
  • 65,235
  • 10
  • 71
  • 111
  • "If you use typeid().name() [..] you get the name of the type" - Yeah, I know : ) I just used that as a way to test that I was getting the type I wanted, since I didn't know how to "return" a type. – SlySherZ Sep 07 '17 at 14:54
  • @SlySherZ - I think you should explain this in your question; as you can see, you're getting answers tailored to get the name of the type where getting the type with a type traits is very simple. – max66 Sep 07 '17 at 16:31