了解Boost.Hana快速入门

问题描述

我正在研究Boost.Hana's User Manual,以了解有关C ++中的模板元编程和函数式编程的更多信息。

关于Real world example,我仍然想念一些,全部集中在以下函数的定义上:

template<typename Any,typename Default,typename Case,typename ...Rest>
auto process(Any a,std::type_index const& t,Default default_,Case& case_,Rest ...rest) {
    using T = typename decltype(+hana::first(case_))::type;
    return typeid(T) == t ? hana::second(case_)(*boost::unsafe_any_cast<T>(&a))
                          : process(a,t,default_,rest...);
};

这是我的疑问和疑问:

  • 关于using指令,我确实知道T是要存储在first的{​​{1}}条目中的类型,即用case_获得的一对,但是为什么这么复杂呢?我对所有这些hana::make_pair::typedecltypetypename感到困惑。它们如何彼此交互(在这种情况下,如果这个问题看起来很笼统)?

    • 嗯,需要的hana::type_c确实让我感到困惑。有什么用?
  • 一旦我认为+是我需要的那种类型,为什么我要按T进行比较?

    • std::type_index中,我读到 typeid(T) == t类是围绕type_index对象的包装类
    • std::type_info中我读到,std::type_info包含有关类型的特定于实现的信息,包括类型的名称用于比较两种类型是否相等的方法。 strong>或整理顺序
    • 并且从typeid中我读了(参考用法type_info)是指表示类型类型的typeid(type)对象

    这似乎都是相关的,但是我不知道如何将std::type_info类的typeid(T)std::type_info进行比较,后者是通过调用{{1 }} std::type_index上的成员函数,我不知道它来自哪里。我希望有人能帮助我理解这一点。

  • type为true的return语句中,为什么需要atypeid(T) == t不起作用?

解决方法

我将尝试回答有关using这一行的问题:

  • case_hana::pair创建的hana::make_pair(hana::type_c<T>,f)类型的变量(第一个参数是类型的包装器)
  • hana::first(case_)返回该对中的第一项(围绕该类型的hana :: type_c包装器)
  • +hana::first(case_)使用一元加号将值从左值转换为右值(请参见https://www.boost.org/doc/libs/1_68_0/libs/hana/doc/html/structboost_1_1hana_1_1type.html
  • decltype(+hana::first(case_))评估为该对中第一项的类型(hana :: type_c包装器)
  • decltype(+hana::first(case_))::type返回该对中第一项的实际类型(无论是在hana :: type_c内部构造的那种类型)
  • using T = typename decltype(+hana::first(case_))::type;将原始类型命名为T(需要使用typename位,因为C ++是一种复杂的语言,有时编译器需要提示事物是否为类型)

您需要一些机制来提取传递给hana :: make_pair的原始类型-如果您要构建一些东西来仅解决您的特定问题,则会使其变得更简单,但是它们需要使库如此通用,以至于解决每个人的问题,这增加了复杂性。

第二return行:

该示例的整个前提是switch_被传递了boost :: any,并使用boost :: any的内容调用了正确的lambda。

hana::second(case_)是最初提供给switch_的lambda之一,因此,如果您使用hana::second(case_)(a),则boost :: any会传递给您的lambda,但lambda内部的代码却不会期望boost :: any,所以错误消息显示std :: to_string不接受boost :: any。

您实际上可以使用hana::second(case_)(a),然后将boost :: any参数转换回lambda内部的原始类型。那实际上可以很好地工作,但是我认为switch_应该为您做些事情,以便lambda获得您期望的类型。

不幸的是,boost :: any需要如此糟糕的转换语法。