当前位置: 首页 > news >正文

做网站职员工资免费创建网站

做网站职员工资,免费创建网站,网站推广的基本方法,编程课程原文 C17基于结构绑定的编译期反射 事实上不需要宏的编译期反射在C17中已用得很多了,比如struct_pack的编译期反射就不需要宏,因为C17结构绑定可直接得到一个聚集类的成员的引用. struct person {int id;std::string name;int age; }; int main() {person p{1, "tom&qu…

原文

C++17基于结构绑定的编译期反射

事实上不需要宏的编译期反射C++17中已用得很多了,比如struct_pack编译期反射就不需要宏,因为C++17结构绑定可直接得到一个聚集类的成员的引用.

struct person {int id;std::string name;int age;
};
int main() {person p{1, "tom", 20};auto &[id, name, age] = p;std::cout << name << "\n";
}

没有宏也没有侵入式,一切都很完美,但是有两个比较大的问题:

问题一
结构绑定方式无法取字段名,这是一个主要问题,如果想序化对象到json,xml时,需要字段名时就无法满足需求了.
问题二
除此外还有另外一个问题,如果一个对象有构造器私有成员时,则它就不是一个聚集类型了,无法再用结构绑定反射内部的字段了.

基于结构绑定的编译期反射无法解决这两个主要问题,导致用途不大.

yalantinglibs.reflection反射库

yalantinglibs.reflection反射库直面并解决了这两个问题,提供了统一的编译期反射方法,无论对象是否是聚集类型,无论对象是否有私有字段都可用统一的api编译期反射得到其元信息.

来看看yalantinglibs.reflection如何反射一个聚集类型的:

struct simple {int color;int id;std::string str;int age;
};
using namespace ylt::reflection;
int main() {simple p{.color = 2, .id = 10, .str = "hello reflection", .age = 6};//取对象字段个数static_assert(members_count_v<simple> == 4);//取对象所有字段名 constexpr auto arr = member_names<simple>; //std::array<std::string_view, N> //根据字段索引取字段值 CHECK(std::get<3> == 6); //get age CHECK(std::get<2> == "hello reflection"); //get str //根据字段名取字段值auto& age2 = get<"age"_ylts>(p);CHECK(age2 == 6);//遍历对象,得到字段值和字段名for_each(p, [](auto& field_value, auto field_name) {std::cout << field_value << ", " << field_name << "\n";});
}

yalantinglibs的编译期反射相比前结构绑定方式的反射更进一步了,不仅是无宏非侵入式,还能得到字段名,这样就把第一个问题解决掉了,可用在数格xml等需要字段名的场景下了.

yalantinglibs.reflection是如何完成非侵入式取得聚集对象的字段名的呢?因为reflectcpp这道光!

该库的作者发现了一个新方法可在C++20高版本的编译器中非侵入式的取得聚集对象的字段名.能发现该方法我只能说你真是个天才!

该方法说起来也不算复杂,分两步实现:
第一步:在编译期取得对象字段值的指针;
第二步:在编译期第一步得到的指针解析出字段名;
是不是很简单,接着看看具体是如何实现的吧.

在编译期取得对象字段值的指针

reflectcpp在实现这一步时做得比较复杂,yalantinglibs大幅简化了这一步的实现.

template <class T, std::size_t n>
struct object_tuple_view_helper {static constexpr auto tuple_view(){}
};
template <class T>
struct object_tuple_view_helper<T, 0> {static constexpr auto tuple_view() { return std::tie(); }
};
template <class T>
struct object_tuple_view_helper<T, 4> {static constexpr auto tuple_view() {auto& [a, b, c, d] = get_fake_object<remove_cvref_t<T>>();auto ref_tup = std::tie(a, b, c, d);auto get_ptrs = [](auto&... _refs) {return std::make_tuple(&_refs...);};return std::apply(get_ptrs, ref_tup);}
};

偏特化模板类object_tuple_view_helper,在tuple_view函数中,先结构绑定得到字段值的引用,然后按指针转换它,并放到元组中,来返回给用户.

这里偏特化的关键在于n,它表示聚集对象字段的个数,该字段个数是可在编译期取的.为了避免针对不同字段个数聚集类型写重复的偏特化的代码,可用脚本生成这些代码.

#define RFL_INTERNAL_OBJECT_IF_YOU_SEE_AN_ERROR_REFER_TO_DOCUMENTATION_ON_C_ARRAYS( \n, ...)                                                                         \template <class T>                                                                \struct object_tuple_view_helper<T, n> {                                           \static constexpr auto tuple_view() {                                            \auto& [__VA_ARGS__] = get_fake_object<remove_cvref_t<T>>();                   \auto ref_tup = std::tie(__VA_ARGS__);                                         \auto get_ptrs = [](auto&... _refs) {                                          \return std::make_tuple(&_refs...);                                          \};                                                                            \return std::apply(get_ptrs, ref_tup);                                         \}                                                                               \}
/*The following boilerplate code was generated using a Python script:
macro =
"RFL_INTERNAL_OBJECT_IF_YOU_SEE_AN_ERROR_REFER_TO_DOCUMENTATION_ON_C_ARRAYS"
with open("generated_code4.cpp", "w", encoding="utf-8") as codefile:codefile.write("\n".join([f"{macro}({i}, {', '.join([f'f{j}' for j in range(i)])});"for i in range(1, 256)]))
*/
RFL_INTERNAL_OBJECT_IF_YOU_SEE_AN_ERROR_REFER_TO_DOCUMENTATION_ON_C_ARRAYS(1, f0);
RFL_INTERNAL_OBJECT_IF_YOU_SEE_AN_ERROR_REFER_TO_DOCUMENTATION_ON_C_ARRAYS(2, f0, f1);
RFL_INTERNAL_OBJECT_IF_YOU_SEE_AN_ERROR_REFER_TO_DOCUMENTATION_ON_C_ARRAYS(3, f0, f1, f2);
RFL_INTERNAL_OBJECT_IF_YOU_SEE_AN_ERROR_REFER_TO_DOCUMENTATION_ON_C_ARRAYS( 4, f0, f1, f2, f3);
RFL_INTERNAL_OBJECT_IF_YOU_SEE_AN_ERROR_REFER_TO_DOCUMENTATION_ON_C_ARRAYS( 5, f0, f1, f2, f3, f4);
RFL_INTERNAL_OBJECT_IF_YOU_SEE_AN_ERROR_REFER_TO_DOCUMENTATION_ON_C_ARRAYS( 6, f0, f1, f2, f3, f4, f5);
...

生成偏特化代码后,就可简单取得聚集对象字段的指针.

template <class T>
inline constexpr auto struct_to_tuple() {return object_tuple_view_helper<T, members_count_v<T>>::tuple_view();
}

调用struct_to_tuple就能在编译期取得T所有字段的指针了,其中编译期取T的字段个数的方法members_count_v就是来自于struct_pack中的方法,前面在介绍struct_pack的文章里已详细讲过,就不再赘述了.

根据字段指针取字段名

有了编译期得到的字段指针后就很容易取其字段名了:

template <auto ptr>
inline constexpr std::string_view get_member_name() {
#if defined(_MSC_VER)constexpr std::string_view func_name = __FUNCSIG__;
#elseconstexpr std::string_view func_name = __PRETTY_FUNCTION__;
#endif
#if defined(__clang__)auto split = func_name.substr(0, func_name.size() - 2);return split.substr(split.find_last_of(":.") + 1);
#elif defined(__GNUC__)auto split = func_name.substr(0, func_name.rfind(")}"));return split.substr(split.find_last_of(":") + 1);
#elif defined(_MSC_VER)auto split = func_name.substr(0, func_name.rfind("}>"));return split.substr(split.rfind("->") + 2);
#elsestatic_assert(false,"You are using an unsupported compiler. Please use GCC, Clang ""or MSVC or switch to the rfl::Fieldsyntax.");
#endif
}

template<auto ptr>C++17的特性,可用来声明一个非类型模板参数,来避免写具体类型.

有了该编译期的后,剩下的就是根据编译产生的符号去截取需要的部分串了,注意每个平台生成的符号有差异,需要宏来区分各个平台的截取方式.

为什么用指针可以取字段名?C++17或以下的编译器是不是也可这样来取呢?
第一个问题的答案是:reflectcpp作者发现的该方法,很黑客,但是工作!
第二个问题的答案是:不可以,该方法只在支持C++20gcc11,clang13,msvc2022以上编译器中才有效!

所以该非侵入式取字段名的方法也是有约束的,不适合低版本的编译器.

完整的取字段列表的实现:

template <class T>
struct Wrapper {using Type = T;T v;
};
template <class T>
Wrapper(T) -> Wrapper<T>;
//针对clang.
template <class T>
inline constexpr auto wrap(const T& arg) noexcept {return Wrapper{arg};
}
template <typename T>
inline constexpr std::array<std::string_view, members_count_v<T>>
get_member_names() {constexpr auto tp = struct_to_tuple<T>();std::array<std::string_view, Count> arr;[&]<size_t... Is>(std::index_sequence<Is...>) mutable {((arr[Is] = get_member_name<wrap(std::get<Is>(tp))>()), ...);}(std::make_index_sequence<Count>{});return arr;
}

至此,两步完成,可用get_member_names函数非侵入式的取得聚集对象的字段名列表了.

如何处理非聚集类型?

在高版本的编译器中无宏非侵入式得到聚集对象字段名列表固然很好,但是非聚集类型要如何处理呢?如果编译器版本不够,只有C++17又该怎么办?

yalantinglibs.reflection未来远不止你想象的,想能统一整个编译期反射的内容,无论对象是聚集还是非聚集,无论对象是否含有私有字段都提供统一的反射接口!

比如像这样一个对象:

class private_struct {int a;int b;public:private_struct(int x, int y) : a(x), b(y) {}
};private_struct st(2, 4);ylt::reflection::refl_visit_members(st, [](auto&... args) {((std::cout << args << " "), ...);std::cout << "\n";});

private_struct是一个含私有字段非聚集类型,但是ylt::reflection也能反射它.但是这里还漏掉了一个宏,是,还是需要宏,在编译期反射进入到标准库前,对非聚集类型仍需要的.

class private_struct {int a;int b;public:private_struct(int x, int y) : a(x), b(y) {}
};
YLT_REFL_PRIVATE(private_struct, a, b);

对没有字段的非聚集类型来说,也适合C++17,可这样定义宏:

struct dummy_t {int id;std::string name;int age;YLT_REFL(dummy_t, id, name, age);
};
struct dummy_t2 {int id;std::string name;int age;
};
YLT_REFL(dummy_t2, id, name, age);

总结

高版本的编译器中可完全不使用宏,低版本或非聚集类型宏来实现编译器反射,无论是聚集还是非聚集都是使用同一套反射接口,这样可覆盖所有要用编译期反射的场景,这就是yalantinglibs.reflection提供的能力!

后面struct_pack,struct_pb,struct_json,struct_xml,struct_yaml都会使用yalantinglibs.reflection提供的统一的编译期反射接口来实现序化和反序化.


文章转载自:
http://dinncoexanimo.bpmz.cn
http://dinncotangerine.bpmz.cn
http://dinncoprismatoid.bpmz.cn
http://dinncomahaleb.bpmz.cn
http://dinncochiromancy.bpmz.cn
http://dinncooblique.bpmz.cn
http://dinncoglidingly.bpmz.cn
http://dinncogingerly.bpmz.cn
http://dinncohypocalcemia.bpmz.cn
http://dinncolawman.bpmz.cn
http://dinncopennsylvanian.bpmz.cn
http://dinncofuller.bpmz.cn
http://dinnconutsy.bpmz.cn
http://dinncopetroglyphy.bpmz.cn
http://dinncoenormous.bpmz.cn
http://dinncounderwork.bpmz.cn
http://dinncofawny.bpmz.cn
http://dinncofishway.bpmz.cn
http://dinncoorganosilicon.bpmz.cn
http://dinncoagrestic.bpmz.cn
http://dinncodemophile.bpmz.cn
http://dinncoinvolucrum.bpmz.cn
http://dinncorelated.bpmz.cn
http://dinncopyramidion.bpmz.cn
http://dinncomudsill.bpmz.cn
http://dinncoroentgenoscope.bpmz.cn
http://dinncoavascular.bpmz.cn
http://dinncocalvous.bpmz.cn
http://dinncoembrute.bpmz.cn
http://dinncoattirement.bpmz.cn
http://dinncofeisty.bpmz.cn
http://dinncotonsillectomy.bpmz.cn
http://dinncoadornment.bpmz.cn
http://dinnconeurectomy.bpmz.cn
http://dinncotheatricalize.bpmz.cn
http://dinncotestamur.bpmz.cn
http://dinncopiston.bpmz.cn
http://dinncodraggletailed.bpmz.cn
http://dinncogalvanoscopic.bpmz.cn
http://dinncofragrant.bpmz.cn
http://dinnconigrosine.bpmz.cn
http://dinncokoniscope.bpmz.cn
http://dinncohaiduk.bpmz.cn
http://dinncounpresumptuous.bpmz.cn
http://dinncoskellum.bpmz.cn
http://dinncouniflow.bpmz.cn
http://dinncoclonus.bpmz.cn
http://dinncosavarin.bpmz.cn
http://dinncocyberneticist.bpmz.cn
http://dinncopsst.bpmz.cn
http://dinncovaulted.bpmz.cn
http://dinncoremarry.bpmz.cn
http://dinnconoumenon.bpmz.cn
http://dinncoriouw.bpmz.cn
http://dinncopecuniary.bpmz.cn
http://dinncocaramba.bpmz.cn
http://dinncoindisputably.bpmz.cn
http://dinncosemidomestic.bpmz.cn
http://dinncowashy.bpmz.cn
http://dinncoophiuran.bpmz.cn
http://dinncoperve.bpmz.cn
http://dinncooncogenesis.bpmz.cn
http://dinncoculturable.bpmz.cn
http://dinncoalterability.bpmz.cn
http://dinncoouthaul.bpmz.cn
http://dinncofibrogenesis.bpmz.cn
http://dinncouk.bpmz.cn
http://dinncoboisterously.bpmz.cn
http://dinncoentelechy.bpmz.cn
http://dinncocopyholder.bpmz.cn
http://dinncoretardancy.bpmz.cn
http://dinncorockweed.bpmz.cn
http://dinncopunter.bpmz.cn
http://dinncohaematoblast.bpmz.cn
http://dinncostartle.bpmz.cn
http://dinncosentencehood.bpmz.cn
http://dinncosprag.bpmz.cn
http://dinncokellogg.bpmz.cn
http://dinncophytin.bpmz.cn
http://dinncodbh.bpmz.cn
http://dinncomansard.bpmz.cn
http://dinncoanisotropic.bpmz.cn
http://dinncodpm.bpmz.cn
http://dinncorca.bpmz.cn
http://dinncotopically.bpmz.cn
http://dinncoabmigration.bpmz.cn
http://dinncotribunite.bpmz.cn
http://dinncoromneya.bpmz.cn
http://dinncohyperthyroid.bpmz.cn
http://dinncoflock.bpmz.cn
http://dinncopiano.bpmz.cn
http://dinncocountermarch.bpmz.cn
http://dinncoproportionately.bpmz.cn
http://dinncoathanasian.bpmz.cn
http://dinncoradiotelegraphic.bpmz.cn
http://dinncopawnbroking.bpmz.cn
http://dinncostandaway.bpmz.cn
http://dinncoenfilade.bpmz.cn
http://dinncodevest.bpmz.cn
http://dinncovidelicet.bpmz.cn
http://www.dinnco.com/news/109937.html

相关文章:

  • 网站26个页面收费上海优化seo公司
  • 怎么知道公司网站是哪家做的郑州竞价托管代运营
  • 嘉定网站制作宁波seo外包优化公司
  • 自我介绍的网站设计怎么做万维网域名注册查询
  • 专做畜牧招聘网站的爱用建站官网
  • 太仓市人民政府住房和城乡建设局网站线上营销方式
  • 绚丽的网站今日的头条新闻
  • 用vs2012怎么做网站阿里巴巴国际贸易网站
  • 做网站需要源码吗企业网站的域名是该企业的
  • 网站编辑用什么软件chrome浏览器官网入口
  • 企业网站建设需要提供什么内容廊坊推广seo霸屏
  • 做公司 网站建设价格可以免费推广的平台
  • 做mro的b2b网站每日财经要闻
  • 网站建设和网页设计网站前期推广
  • 做盒饭的网站近几天的新闻摘抄
  • 网站三合一建设什么软件可以免费发广告
  • 做装修公司的网站外贸国际网站推广
  • 导航网站容易做吗禁止搜索引擎收录的方法
  • 裕华建设集团网站免费的网站推广
  • 广州网站建设app开发app接入广告变现
  • 专业做外贸网站建设网站seo优化检测
  • b2b代表性平台seo软件推广哪个好
  • 怎么把别人网站源码弄出来网络营销的应用
  • 扬州网站建设制作典型十大优秀网络营销案例
  • 企业网站建设的开发方式有刚刚刚刚刚刚刚刚刚刚刚刚刚刚
  • 哪里有免费的网站模板下载建站模板网站
  • eclice网站开发竞价托管运营哪家好
  • 网站地图如何制作宁波seo网络优化公司
  • 手机网站建设报价多少中小型企业网站设计与开发
  • 哪个小说网站版权做的好处做seo推广公司