网站首页 文章专栏 c++2a的std::is_detected
c++2a的std::is_detected
编辑时间:2019-01-05 16:54:09 作者:qicosmos 5条评论


    出自:purecpp

    地址: www.purecpp.org

    转载请注明出处!


来说两句吧
最新评论
  • qicosmos
    star 2019-01-06 13:51:40

    template<class T, typename... Args>

    using has_foo_t = decltype(std::declval<T>().foo(std::declval<Args>()...));

    个人认为核心就这一句,探测类中是否有某个方法签名,就是用上面类似的方法实例出来说可以了。若不能实例出,则直接在编译期报错,这个错误并不会漫延到运行期。这从另一个角度上来说,在此方法上的detected封闭是不是还有如此必要?

  • qicosmos
    qicosmos 2019-01-06 21:12:45
    @star 实际应用需求不能编译报错,需要得到到底有没有这个方法的true/false
  • qicosmos
    star 2019-01-07 21:46:25

    试着解释一下is_detected的实现。这个理解花了好半天时间,不知对错,请指正。@qicosmos

    从结果来逆推其实现

    template<class T, typename... Args>

    using has_foo_t = decltype(std::declval<T>().foo(std::declval<Args>()...));

    定义了has_foo_t模板函数类型,此处该函数类型的实例化会推到最后,并不会在当前实例化,故此时不会报编译错误的。

    template<typename T, typename... Args>

    using has_foo2 = is_detected<has_foo_t, T, Args...>;

    template<template<class...> class Op, class... Args>

    using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;

    再看这两个类型别名,has_foot_t是前面以定义的模板函数类型,作为 下式的 Op传入具体的模板类型detector


    再来看最后detector的定义:


    template<class Default, class AlwaysVoid, template<class...> class Op, class... Args> struct detector

    { using value_t = std::false_type; using type = Default; };

    template<class Default, template<class...> class Op, class... Args>

    struct detector<Default, std::void_t<Op<Args...>>, Op, Args...>

    { using value_t = std::true_type; using type = Op<Args...>; };

    原类型的定义有一个偏特化定义,即当第二个参数为void时,先试图用此偏特化处理该类型,从上面is_detected传入的可以看到,其第二个参数恰是void,则此时,我们会试图用这个偏特化来完成类型的定义,但此时我们传入的模板函数类型若不能结合后面的参数实例化时,根据SFINEA原则,此时会去匹配原定义,原定义是可以匹配成功的,因为不会试图实例化该foo函数模板类型,故我们可以发现在编译的整个过程中,推迟和隐藏了不可能实例化函数。

  • qicosmos
    star 2019-01-07 22:34:51

    另关于类型的定义,文中的定义方式在探测不到我们希望的结果时,只会默认返回一个delete 类。

    我私认为可能比较好的方式,是给出默认类型,即当不匹配时返回我们自已给出的类型。所以关于类型这一块可以如此改动。不知可否。

    template<class default,template<class...> class Op, class... Args>

    using detected_t = typename detector<default, void, Op, Args...>::type;

    //

    template<typename Default, typename T, typename... Args>

    using has_foo2_t = is_detected<Default, has_foo_t, T, Args...>;

    //测试

    static_assert(std::is_same_v<has_foo_t<bool,A,int,int,int>,bool>);

  • qicosmos
    qicosmos 2019-01-08 15:34:16
    改成自定义的类型作为默认类型也是没问题的,我觉得用nosuch会更好,因为这个自定义类型没有多大意义,纯粹是为了表明没有探测到类型,而且加了自定义类型后使用起来需要传入的参数更多,用起来不够简洁。
Absolutely

purecpp

一个很酷的modern c++开源社区


这里有创新的idea,这里有最酷的modern c++代码,这里有很棒的modern c++开源项目。purecpp社区邮箱 purecpp@163.com
友情链接