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

炸鱼薯*_*德里克 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)


And*_*ner 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>> {}
Run Code Online (Sandbox Code Playgroud)

  • 这取决于`remove_cv_t`是`decay_t`的子集.后者也将删除特征通常所需的参考(r值和l值).除非你不想要找'的std ::组<...>&`和`的std ::组<...> &&`. (3认同)