如何检测类型是否为std :: tuple?

时间:2017-09-07 10:02:41

标签: c++ c++11 template-meta-programming sfinae

为什么我的代码有奇怪的输出?如何以正确的方式测试类型?

#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,我得到输出&#34; 01&#34; 为什么我有两个不同的输出? Aren他们是同一类型吗?

3 个答案:

答案 0 :(得分:16)

decltype(ItemTemplate::traits)const std::tuple<TraitBlock, TraitRock>

所以你必须在某处处理cv限定符。

答案 1 :(得分:13)

请注意,ItemTemplate::traits(即decltype(ItemTemplate::traits))的类型为const std::tuple<TraitBlock, TraitRock>,与{{}的特化中的指定类型(即std::tuple<Ts...>)不匹配1}}。

您可以通过std::remove_const删除常量,例如

is_tuple

或为std::cout << is_tuple<std::remove_const_t<decltype(ItemTemplate::traits)>>::value; 添加其他专精(也可能const):

volatile

答案 2 :(得分:7)

您需要删除所有限定符。您应该使用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>> {}