In the code below, I'm trying to determine the type of elements inside a container by checking whether a container C has member value_type. If true, I set the type to "value_type". However even when a type doesn't have member value_type and isn't a container, when passed, compiler seems to set the second argument of HasMemberT_value_type to True, even though it gives error.
template<typename...>
using void_t = void;
template<typename T, typename = void_t<>>
struct HasMemberT_value_type : std::false_type
{
};
template<typename T>
struct HasMemberT_value_type<T, void_t<typename T::value_type>> : std::true_type
{
};
template<typename T, bool = HasMemberT_value_type<T>::value>
struct ElementTypeT
{
using Type = typename T::value_type;
};
template<typename T>
struct ElementTypeT<T, false>
{
};
template<typename T>
using ElementType = typename ElementTypeT<T>::Type;
template<typename T>
void printType(T const& c)
{
std::cout << "Container of " << typeid(ElementType<T>).name() << " elements.\n";
}
int main()
{
std::array<char, 5> arr;
char classic[] = {'a', 'b', 'c', 'd'};
//GNU Compiler:
printType<arr>(); //Container of c elements.
printType<classic>(); //ERROR : "In instantiation of ‘struct ElementTypeT<char [4], true>’: ... error: ‘char [4]’ is not a
// class, struct, or union type
// using Type = typename T::value_type;"
}
In instantiation of ‘struct ElementTypeT<char [4], true>
why is it set to true??
Thank you.
printType<arr>()andprintType<classic>()won't compile. It should beprintType(arr)andprintType(classic).The other problem is that
ElementTypeT<T, true>has aTypemember, butElementTypeT<T, false>does not. So when you dousing ElementType = typename ElementTypeT<T>::Typeand access that when you doprintType(classic), it will fail.To fix this, modify the specialization so that the array can be deduced:
Not sure why
ElementTypeT<char [4], true>is instaniating in your code. When I ran it it came upfalsefor me.Here's a simpler way to do this using function overloading and SFINAE: