如何检测类型是否为 std::tuple?
How to detect whether a type is std::tuple or not?
为什么这段代码的输出很奇怪?如何以正确的方式测试类型?
#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;
}
我使用 mingw64-gcc 7.2.0 和 -std=c++17,我得到输出“01”
为什么我得到两个不同的输出?他们不是同一种类型吗?
decltype(ItemTemplate::traits)
是 const std::tuple<TraitBlock, TraitRock>
.
所以你必须在某处处理 cv 限定符。
请注意,ItemTemplate::traits
(即decltype(ItemTemplate::traits)
)的类型是const std::tuple<TraitBlock, TraitRock>
,与特化中指定的类型(即std::tuple<Ts...>
)不匹配is_tuple
.
您可以通过 std::remove_const 删除常量,例如
std::cout << is_tuple<std::remove_const_t<decltype(ItemTemplate::traits)>>::value;
或为 const
添加另一个专业(也可能 volatile
):
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 {};
您需要删除所有限定词。你应该使用 std::decay_t
来代替你自己做这一切,它会为你删除所有限定符并分配给你的特征。例如
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>> {}
为什么这段代码的输出很奇怪?如何以正确的方式测试类型?
#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;
}
我使用 mingw64-gcc 7.2.0 和 -std=c++17,我得到输出“01” 为什么我得到两个不同的输出?他们不是同一种类型吗?
decltype(ItemTemplate::traits)
是 const std::tuple<TraitBlock, TraitRock>
.
所以你必须在某处处理 cv 限定符。
请注意,ItemTemplate::traits
(即decltype(ItemTemplate::traits)
)的类型是const std::tuple<TraitBlock, TraitRock>
,与特化中指定的类型(即std::tuple<Ts...>
)不匹配is_tuple
.
您可以通过 std::remove_const 删除常量,例如
std::cout << is_tuple<std::remove_const_t<decltype(ItemTemplate::traits)>>::value;
或为 const
添加另一个专业(也可能 volatile
):
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 {};
您需要删除所有限定词。你应该使用 std::decay_t
来代替你自己做这一切,它会为你删除所有限定符并分配给你的特征。例如
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>> {}