C ++两个is_union_or_class实现

时间:2017-07-09 17:54:40

标签: c++ templates typetraits

我尝试使用以下方法实现is_union_or_class,首先没有void_t

#include <type_traits>

    namespace detail {
        template <class T>
        struct is_union_or_class_helper1 : public std::false_type { };
        template <class T>
        struct is_union_or_class_helper1<char T::*> : public std::true_type { };
    }

template <class T>
struct is_union_or_class1 : public detail::is_union_or_class_helper1<T> { };

然后我使用虚拟空类测试它,value成员评估为false。然后我使用void_t重试它:

#include <type_traits>

template <class...>
using void_t = void;

    namespace detail {
        template <class T, class = void_t<T>>
        struct is_union_or_class_helper2 : public std::false_type { };
        template <class T>
        struct is_union_or_class_helper2<T, void_t<char T::*>> : public std::true_type { };
    }

template <class T>
struct is_union_or_class2 : public detail::is_union_or_class_helper2<T> { };

这一次它正确地评估了true。为什么结果不同?在char T::*是有效表达式的情况下,两个助手都更专业,为什么只有在第二种情况下助手继承自true_type?这是测试代码:

struct dummy_type { };

int main(int argc, char** argv) {
    std::cout << is_union_or_class1<dummy_type>::value << "\n";
    std::cout << is_union_or_class2<dummy_type>::value << "\n";
}

我使用MSVC 2015编译器编译了此代码并进行了测试。

1 个答案:

答案 0 :(得分:1)

考虑一下:

is_union_or_class1<dummy_type>::value

dummy_type不是指向要推导出的类T的char类型的数据成员的指针。换句话说,dummy_type(我说)不匹配类型char T::*,此专业化将被废弃。
因此,选择了类模板,并且该模板继承自std::false_type

template <class T>
struct is_union_or_class_helper1 : public std::false_type { };

这样的事情会起作用:

    template <class T, typename = T>
    struct is_union_or_class_helper1 : public std::false_type { };
    template <class T>
    struct is_union_or_class_helper1<T, decltype((char T::*){}, T{})> : public std::true_type { };

这只不过是void_t成语的另一种变体 让我重写一下:

    template <class T, typename = void>
    struct is_union_or_class_helper1 : public std::false_type { };
    template <class T>
    struct is_union_or_class_helper1<T, decltype((char T::*){}, void())> : public std::true_type { };

它就是那些仍然在等待C ++ 17的void_t成语的形式之一。