Reputation: 999
Why I have strange output for this code? How to test for a type in the right way?
#include <iostream>
#include <tuple>
#include <type_traits>
template<typename T> struct is_tuple : std::false_type {};
template<typename... Ts> struct is_tuple<std::tuple<Ts...>> : std::true_type {};
struct TraitBlock {
using BlockLocation = struct { std::uint64_t x, y, z; };
};
struct TraitRock {};
struct ItemTemplate{
static constexpr auto traits = std::make_tuple(
TraitBlock{},
TraitRock{}
);
};
int main(){
using A = std::tuple<char, int,double,char>;
std::cout << is_tuple<decltype(ItemTemplate::traits)>::value
<< is_tuple<decltype(std::make_tuple(
TraitBlock{},
TraitRock{}
))>::value
<< std::endl;
}
I use mingw64-gcc 7.2.0 with -std=c++17, I got output "01" Why I got two different output? Aren't they the same type?
Upvotes: 15
Views: 2490
Reputation: 172924
Note that the type of ItemTemplate::traits
(i.e. decltype(ItemTemplate::traits)
) is const std::tuple<TraitBlock, TraitRock>
, which doesn't match the specified type (i.e. std::tuple<Ts...>
) in the specialization of is_tuple
.
You can remove the const-ness by std::remove_const, e.g.
std::cout << is_tuple<std::remove_const_t<decltype(ItemTemplate::traits)>>::value;
or add another specialization for const
(and might volatile
as well):
template<typename... Ts> struct is_tuple<std::tuple<Ts...>> : std::true_type {};
template<typename... Ts> struct is_tuple<const std::tuple<Ts...>> : std::true_type {};
template<typename... Ts> struct is_tuple<volatile std::tuple<Ts...>> : std::true_type {};
template<typename... Ts> struct is_tuple<const volatile std::tuple<Ts...>> : std::true_type {};
Upvotes: 13
Reputation: 1439
You need to remove all qualifiers. Instead of doing this all yourself you should use std::decay_t
which removes all qualifiers for you and dispatch to your trait. For instance
template<typename T>
struct is_tuple_impl : std::false_type {};
template<typename... Ts>
struct is_tuple_impl<std::tuple<Ts...>> : std::true_type {};
template<typename T>
struct is_tuple : is_tuple_impl<std::decay_t<T>> {}
Upvotes: 9
Reputation: 217255
decltype(ItemTemplate::traits)
is const std::tuple<TraitBlock, TraitRock>
.
So you have to handle cv qualifier somewhere.
Upvotes: 16