炸鱼薯*_*德里克 15 c++ sfinae template-meta-programming c++11
为什么我的代码有奇怪的输出?如何以正确的方式测试类型?
#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;
}
Run Code Online (Sandbox Code Playgroud)
我用mingw64-GCC 7.2.0与-std = C++ 17,我得到了输出"01"为什么我有两个不同的输出?它们不是同一类型吗?
Jar*_*d42 16
decltype(ItemTemplate::traits)是const std::tuple<TraitBlock, TraitRock>.
所以你必须在某处处理cv限定符.
son*_*yao 13
请注意,ItemTemplate::traits(ie decltype(ItemTemplate::traits))的类型const std::tuple<TraitBlock, TraitRock>与特定类型中的指定类型(即std::tuple<Ts...>)不匹配is_tuple.
您可以通过std :: remove_const删除const-ness ,例如
std::cout << is_tuple<std::remove_const_t<decltype(ItemTemplate::traits)>>::value;
Run Code Online (Sandbox Code Playgroud)
或者为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 {};
Run Code Online (Sandbox Code Playgroud)
您需要删除所有限定符.你应该使用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>> {}
Run Code Online (Sandbox Code Playgroud)