C++ SFINAE 学习笔记2 : boost::hana::is_valid

        这次主要学习的内容主要是C++ boost库中的 is_valid 函数,该函数 传入一个lambda表达式,通过判断该 lambda表达式 并返回一个可执行对象( UnnamedType类结构体的一个匿名对象),通过该可调用对象可以判断一个类型是否符合传入的 lambda表达式 中的内容,如:该类型是否含有 .serialize()成员函数 等等。

template<typename UnNameType>//is_valid调用后,UnNameType 为lambda匿名函数的类型
    struct container {
    private:
        template<typename Param>
        auto testValidity(int)-> decltype(declval<UnNameType>()(declval<Param>()), true_type()) {
             // 因为 UnNameType 是 class lambda ,因此 declval<>()是创建一个表达式的lambda函数对象,传入的参数为Param的对象
             // 最终其实还是利用lambda函数来检测 类型是否含有 .serialize这个成员
             return true_type();
        }//true_type() 重载 等同于true_type::value

        template<typename Param>
        constexpr auto testValidity(...) {
            return false_type();
        }
        
    public:
        template<typename Param>
        constexpr auto operator() (const Param&  obj){
            cout << "operator():Param:" << typeid(Param).name() << endl;
            return testValidity<Param>(int());
        }

    };
    //传递lambda函数的方式有两种,1.利用模版进行传递  2.利用std::function<type (Param)> & obj
    template<typename UnNameType>
    constexpr auto is_valid(const UnNameType& obj) {
        return container<UnNameType>();
        //返回的是一个类型为container<UnNameType>的 类结构体的匿名对象 ,供后面的test调用operator()函数
    }

    auto hasserialize = is_valid([](auto&& obj) ->decltype(obj.serialize()) { return obj.serialize(); });
    
    template<typename T>
    auto serialize(T& obj)->typename enable_if< decltype(hasserialize(obj))::value ,string >::type{
        return obj.serialize();
    }

    template<typename T>
    auto serialize(T& obj)->typename enable_if< !decltype(hasserialize(obj))::value ,std::string >::type{
        return to_string(obj);
    }

    void test_for_hana() {
        A a;
        B b;
        C c;
        auto test = is_valid([](const auto& t) -> decltype(t.serialize()) {});

        std::cout << test(a) << std::endl;
        std::cout << test(b) << std::endl;
        std::cout << test(c) << std::endl;

        // serialize 函数即是对 is_valid 函数的一层封装,通过判断是否存在serialize对象,并输出不同方式的序列化结果
        std::cout << serialize(a) << std::endl;
        std::cout << serialize(b) << std::endl;
        std::cout << serialize(c) << std::endl;
    }

      enable_if 的使用:enable_if<A,B>::type  如果表达式 A 的值为 true 那么 enable_if<>::type的类型即为 表达式模板参数B的类型

         is_valid函数 利用 class container 来进行 判断该类型是否含有某一成员函数,或者该类型是否符合某种使用方法。 class container 接受is_valid 传入的 class lambda 类型,在is_valid 中的 return container<UnNameType>(); 返回语句,在C++ 中遇到 A()  时,会在 返回A的临时匿名对象 和 返回 类型为A的无参函数之间 进行选择,如果不是前后语义进行限制的话,会有限选择返回 返回类型为A的无参函数,但是因为本题中后续 会将 is_valid 函数的返回值作为一个可调用的对象来进行使用,因此返回值是一个可执行对象(函数),而container 声明了operator()这么一个重载函数,意味着 container类对象 可以作为仿函数进行使用。

        因此 ,is_valid 函数 接受一个lambda 对象, 返回一个验证 该lambda对象行为 的含有一个参数的可执行对象。(通俗来讲,is_valid 的返回值可以其参数<一个类型的对象> 的行为是否符合传入 is_valid 函数的lambda表达式的行为

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值