How to determine the type of an array element?
Asked Answered
C

4

9

I can't get the type of an element. This solution returns a reference to element type.

int arr[] = { 0, 1, 2, 3, 4, 5 };
using arrElemType = decltype(*arr);
vector<arrElemType> vec(std::cbegin(arr), std::cend(arr));
Cayes answered 14/3, 2014 at 16:20 Comment(4)
Type traits to the rescue!Chrisoula
You can use typeid msdn.microsoft.com/en-us/library/fyf39xec%28v=vs.110%29.aspxRettke
@Cyber: That's a non-standard, non-portable precursor to decltype.Wiring
Not an answer to your question but since C++ 17 there is CTAD where you don't need the type specified. That won't help for all cases.Horsy
S
13

Try the following

using arrElemType = std::remove_reference<decltype( *arr )>::type;

or

typedef std::remove_reference<decltype( *arr )>::type arrElemType;

You need to include header <type_traits>

Stipend answered 14/3, 2014 at 16:38 Comment(1)
I would go all the way and std::decay if I plan on storing it.Trafficator
P
17

The standard way in C++11 and above is to use std::remove_all_extents.

#include <type_traits>

int arr[] = { 0, 1, 2, 3, 4, 5 };
using arrElemType = std::remove_all_extents<decltype(arr)>::type;
vector<arrElemType> vec(std::cbegin(arr), std::cend(arr));
Pyrography answered 16/3, 2018 at 17:45 Comment(0)
S
13

Try the following

using arrElemType = std::remove_reference<decltype( *arr )>::type;

or

typedef std::remove_reference<decltype( *arr )>::type arrElemType;

You need to include header <type_traits>

Stipend answered 14/3, 2014 at 16:38 Comment(1)
I would go all the way and std::decay if I plan on storing it.Trafficator
P
1

Since C++ 11, when only array type is given (not the array variable):

#include <type_traits>

template<typename T>
using array_entry_t = typename std::remove_reference<decltype( std::declval<T>()[0] )>::type;

Full example:

#include <iostream>
#include <typeinfo>
#include <type_traits>

template<typename T>
using array_entry_t = typename std::remove_reference<decltype( std::declval<T>()[0] )>::type;

int main()
{
    using MyArr = char[3];
    std::cout<< typeid(              MyArr ).name() << std::endl; // Prints e.g: A3_c
    std::cout<< typeid(array_entry_t<MyArr>).name() << std::endl; // Prints e.g: c

    return 0;
}
Propeller answered 16/6, 2023 at 20:33 Comment(0)
C
0

My aim here is to give it a go without type_traits. With C++20, we can have lambda in decltype(), so this code works with GCC10.2 flag -std=c++20

int arr[] = { 0, 1, 2, 3, 4, 5 };
using arrElemType = decltype([&](){return arr[0];}()); 
vector<arrElemType> vec(std::cbegin(arr), std::cend(arr));

Pitfall

The below attempt was my first answer which got negative feedback. I kept it for educational purposes so others don't fall into this because of implicit integral type promotion:

uint8_t a;
auto x = +a; // x is int, not uint8_t
auto y = a+a; // y is int, not uint8_t 

So while the example below works, if we change the type of array to uint8_t it will still create vector<int>. OK, now read it:

If + operator is defined for elements:

int arr[] = { 0, 1, 2, 3, 4, 5 };
using arrElemType = decltype(+arr[0]); // + is the key
vector<arrElemType> vec(std::cbegin(arr), std::cend(arr));
  • <type_traits> header is not needed.
  • +arr[0] expression turns to prvalue, which decltype deduces as T.
  • decltype(arr[0]) gives T& which is not desirable here.
  • The array elements are not accessed within decltype, so it doesn't matter if you use arr[1000].
Chuff answered 3/1, 2021 at 18:40 Comment(2)
I think that works in this case because the input is an array of integers. The + is likely to convert the type to int which is probably undesirable (it could be an array of uint8_t).Portia
Thanks @AlexisWilke, very good point, I update my answer.Chuff

© 2022 - 2024 — McMap. All rights reserved.