b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

【c语言在vc++6.0中编写界面程序】

电脑杂谈  发布时间:2019-11-11 03:03:39  来源:网络整理

c语言windows编程视频教程_vc6.0怎么写c语言_c语言贪吃蛇程序

到现在为止,C++ 仍然是计算机编程领域的经典语言之一,C++ 17 标准在2017上半年已经探讨确定。本期我们汇集了编程专家——祁宇(《深入应用 C++ 11》作者,C++ 开源社区 purecpp.org 创始人)的多年心得小结,并具体介绍了 C++ 17 最新标准中值得开发者关注的新特点和基本用法。

文/祁宇

本文将借助分析 magic _ get 源码来介绍 magic _ get 实现的关键科技,深入剖析实现 pod 类型反射的机理。

反射是一种根据元数据来获得类外部信息的模式,通过元数据就可以获得对象的字段和技巧等信息。C# 和 Java 的反射模式都是通过获得对象的元数据来推动的。反射可以用于依赖注入、ORM 对象-实体映射、序列化和反序列化等与对象原本信息密切相关的领域。比如 Java 的 Spring 框架,其依赖注入的基础是构建在反射的基础之上的,可以按照元数据获取类型的信息并动态建立对象。ORM 对象-实体之间的映射也是借助反射实现的。Java 和 C# 都是基于前面运行时的语言,中间运行时提供了反射模式,所以反射针对运行时语言来说很容易,但是针对没有中间运行时的语言,要想实现反射是很困难的。

在2016年的 CppCon 技术大会上,Antony Polukhin 做了一个关于 C++ 反射的发言vc6.0怎么写c语言,他强调了一个实现反射的新思路,即无需使用宏、标记和额外的软件就能推动反射。看起来似乎是一件不也许完成的任务,因为 C++ 是没有反射模式的,无法直接获得对象的元信息。但是 Antony Polukhin 发现对 pod 类型使用 Modern C++ 的模板元方法可以实现这种的编译期反射。他开源了一个 pod 类型的编译期反射库 magic _ get(),这个库也打算开启 boost。我们来看看 magic _ get 的使用示例。

#include <boost pfr="" core.hpp="">struct foo {    int some_integer;    char c;};foo f {777, '!'};auto& r1 = boost::pfr::flat_get<0>(f); //通过索引来访问对象foo的第1个字段auto& r2 = boost::pfr::flat_get<1>(f); //通过索引来访问对象foo的第2个字段</boost>

通过这个例子可以发现,magic _ get 确实实现了非侵入式访问 foo 对象的数组,不需要写任何宏、额外的代码或者专门的软件,直接在编译期就可以访问 pod 对象的数组,没有运行期负担,确实有点 magic。

本文将借助分析 magic _ get 源码来介绍 magic _ get 实现的关键科技,深入剖析实现 pod 类型反射的机理。

实现 pod 类型反射的模式是这么的:先将 pod 类型转化为对应的 tuple 类型,接下来将 pod 类型的值赋给 tuple,然后就可以通过索引去访问 tuple 中的元素了。所以推动 pod 反射的关键就是如何将 pod 类型转化为对应的 tuple 类型和 pod 值数组给 tuple。

pod 类型对应的 tuple 类型是什么样的呢?以下面的 foo 为例,foo 对应的 tuple 应该是 tuple<int, char>,即 tuple 中的元素种类和排序和 pod 类型中的数组完全一一对应。

根据结构体生成一个 tuple 的基本模式是,按次序将结构体中每个数组的类别萃取出来并储存起来,后面再取下来生成对应的 tuple 类型。然而字段的类别是不同的,C++ 也没有一个能直接保存不同类型的容器vc6.0怎么写c语言,因此必须一个变通的方式,用一个间接的方式来储存萃取出来的字段类别,即将类型转化为一个 size _ t 类型的 id,将这个 id 保存到一个 array<size_t, N> 中,后面根据这个 id 来获得实际的 type 并生成对应的 tuple 类型。

这里应该解决的一个问题是怎样推动类型和 id 的互相转换。

c语言windows编程视频教程_c语言贪吃蛇程序_vc6.0怎么写c语言

先通过一个空的模板类用来存放实际的类别,再通过 C++ 14 的 constexpr 特性,在编译期返回某个类别对应的编译期 id,就可以实现 type 转换为 id 了。具体代码如下:

http://ipad-cms.csdn.net/cms/article/code/3445

上面的代码在编译期将类别 int 和 char 做了一个编码,将类别转换为一个具体的编译期常量,后面就可以按照这种编译期常量来获得对应的详细类型。

编译期根据 id 获取 type 的代码如下:

constexpr auto id_to_type( std::integral_constant<std::size_t, 6=""> ) noexcept { int res{}; return res; }constexpr auto id_to_type( std::integral_constant<std::size_t, 9=""> ) noexcept { char res{}; return res; }</std::size_t,></std::size_t,>

上面的代码中 id _ to _ type 返回的是 id 对应的类别的示例,如果要获得 id 对应的类别还必须借助 decltype 推导出来。magic _ get 通过一个宏将 pod 基本类别都做了一个编码,以推动 type 和 id 在编译期的互相转换。

#define REGISTER_TYPE(Type, Index)                                              \    constexpr std::size_t type_to_id(identity<type>) noexcept { return Index; } \    constexpr auto id_to_type( std::integral_constant<std::size_t, index=""> ) noexcept { Type res{}; return res; }  \// Register all base types here    REGISTER_TYPE(unsigned short    , 1)    REGISTER_TYPE(unsigned int      , 2)    REGISTER_TYPE(unsigned long long , 3)    REGISTER_TYPE(signed char       , 4)    REGISTER_TYPE(short             , 5)    REGISTER_TYPE(int               , 6)    REGISTER_TYPE(long long         , 7)    REGISTER_TYPE(unsigned char     , 8)    REGISTER_TYPE(char              , 9)    REGISTER_TYPE(wchar_t          , 10)    REGISTER_TYPE(long             , 11)    REGISTER_TYPE(unsigned long    , 12)    REGISTER_TYPE(void*            , 13)    REGISTER_TYPE(const void*      , 14)    REGISTER_TYPE(char16_t         , 15)    REGISTER_TYPE(char32_t         , 16)    REGISTER_TYPE(float             , 17)    REGISTER_TYPE(double           , 18)    REGISTER_TYPE(long double      , 19)</std::size_t,></type>

将类别编码以后,保存在那里或者怎么取下来是接着要缓解的难题。magic _ get 通过定义一个 array 来保存结构体字段类别 id。

template <class t,="" std::size_t="" n="">   struct array {       typedef T type;       T data[N];       static constexpr std::size_t size() noexcept { return N; }   };</class>

array 中的定长数组 data 中保存数组类型对应的 id,数组下标就是字段在结构体中的位置索引。

前面介绍了怎样实现字段类别的保存和获得,那么这个字段类别是怎样从 pod 结构体中萃取出来的呢?具体的做法分为三步:

下面是详细实现代码:

c语言贪吃蛇程序_c语言windows编程视频教程_vc6.0怎么写c语言

template <class t="">constexpr auto fields_count_and_type_ids_with_zeros() noexcept {    static_assert(std::is_trivial<t>::value, "Not applyable");    array<std::size_t, sizeof(t)=""> types{};    detect_fields_count_and_type_ids<t>(types.data, std::make_index_sequence<sizeof(t)>{});    return types;}template <class t="">constexpr auto array_of_type_ids() noexcept {    constexpr auto types = fields_count_and_type_ids_with_zeros<t>();    constexpr std::size_t count = count_nonzeros(types);    array<std::size_t, count=""> res{};    for (std::size_t i = 0; i < count; ++i) {        res.data[i] = types.data[i];    }        return res;    }</std::size_t,></t></class></sizeof(t)></t></std::size_t,></t></class>

定义 array 时必须定义一个固定的变量长度,长度为多少适合呢?应按结构体最多的字段数来确认。因为结构体的数组数最多为 sizeof(T),所以 array 的长度设置为 sizeof(T)。array 中的元素全部初始化为0。一般情况下,结构体字段数通常不会超过 array 的厚度,那么 array 中就经常出现多余的元素,所以还必须将 array 中多余的数组移除,只储存有效的泛型类别 id。具体的做法是计算出 array 中非零的元素有多少,接着再把非零的元素赋给一个新的 array。下面是推导 array 非零元素个数,同样是通过 constexpr 实现编译期计算。


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-129594-1.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    每日福利
    热点图片
    拼命载入中...