I would like a type trait to get the element type of either a std::array
or a plain old C-style array, eg. it should return char
when provided with either std::array<char, 3>
or char[3]
.
The mechanisms to do this appear to be only partially in place... I can use ::value_type
on the std::array
, and std::remove_all_extents
on the plain array, but I can't find a single type trait that combines both and I'm unable to write one myself.
I've got as far as this:
#include <array>
#include <type_traits>
template <class T>
using element_type = typename std::conditional<
std::is_array<T>::value,
typename std::remove_all_extents<T>::type,
typename T::value_type
>::type;
It works just fine for std::array
, of course:
int main()
{
static_assert(
std::is_same<char, element_type<std::array<char, 3>>>::value,
"element_type failed");
}
but breaks when I pass it a plain array, because obviously plain arrays don't have a ::value_type
.
static_assert(std::is_same<char, element_type<char[3]>>::value, "element_type failed");
just gives errors like "'T': must be a class or namespace when followed by '::'", as you'd expect.
If I were writing a function, I'd use std::enable_if
to hide the offending template instantiation, but I don't see how this approach can be used in a type trait.
What is the correct way to solve this problem?