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

企业网站 优秀石狮外贸网站建设公司报价

企业网站 优秀,石狮外贸网站建设公司报价,seo的概念是什么,营销型 展示类网站相关系列文章 C之std::tuple(二) : 揭秘底层实现原理 C三剑客之std::any(一) : 使用 C之std::tuple(一) : 使用精讲(全) C三剑客之std::variant(一) : 使用 C三剑客之std::variant(二)#xff1a;深入剖析 深入理解可变参数(va_list、std::initializer_list和可变参数模版) st… 相关系列文章 C之std::tuple(二) : 揭秘底层实现原理 C三剑客之std::any(一) : 使用 C之std::tuple(一) : 使用精讲(全) C三剑客之std::variant(一) : 使用 C三剑客之std::variant(二)深入剖析 深入理解可变参数(va_list、std::initializer_list和可变参数模版) std::apply源码分析 目录 1.std::tuple存储设计 2.std::tuple构造 3.std::tuple_size 4.std::get访问值 5.operator 6._Equals 7.总结 之前的章节中讲解std::tuple的使用和一些注意事项接下来我们就以vs2019的std::tuple的实现来讲解它的底层实现原理。 1.std::tuple存储设计 std::tuple存储的递归写法基于这样的思想一个包含N(N0)个元素的元组可以存储为一个元素第1个元素或者说是列表的头部加上一个包含N-1个元素的元组(尾部)而包含0个元素的元组是单独的特殊情况。下面看一下示例 std::tuplebool, int, double, std::string a(true, 1, 3.0, 1112222); 因此一个包含4个元素的元组a的递归构造如下 1) 第一层递归。准备存储a的第一个元素true剩下的是 std:tupleint,double,std::string 对象。 2) 第二层递归。准备存储a的第二个元素1剩下的是 std::tupledouble,std::string 对象。 3) 第三层递归。准备存储a第三个元素3.0, 剩下的是 std::tuplestd::string 对象。 4) 第四层递归。准备存储a第四个元素1112222剩余的是std::tuple遇到std::tuple递归结束。此时a的才开始存储元素并且存储元素是从1112222开始然后递归开始返回。 5) 返回到第3步的递归存储duble类型的3.0。 6) 返回到第2步的递归存储第int类型的1。 7) 返回到第1步的递归存储第bool类型的true。 也就是说std::tuple 的构造函数中最后一个传入的元素最先构造最先传入的元素最后一个构造符合递归顺序即入栈顺序。下面从源码角度具体来看看 std::tuple 的实现。 template class _This, class... _Rest class tuple_This, _Rest... : private tuple_Rest... { // recursive tuple definition public:using _This_type _This; //当前元素using _Mybase tuple_Rest...; //余下的元素//以下都是构造函数罗列了部分template class _Tag, class _This2, class... _Rest2, enable_if_tis_same_v_Tag, _STD _Exact_args_t, int 0constexpr tuple(_Tag, _This2 _This_arg, _Rest2... _Rest_arg): _Mybase(_Exact_args_t{}, _STD forward_Rest2(_Rest_arg)...), _Myfirst(_STD forward_This2(_This_arg)) {}template class _Tag, class _Tpl, size_t... _Indices, enable_if_tis_same_v_Tag, _STD _Unpack_tuple_t, int 0constexpr tuple(_Tag, _Tpl _Right, index_sequence_Indices...);template class _Tag, class _Tpl, enable_if_tis_same_v_Tag, _STD _Unpack_tuple_t, int 0constexpr tuple(_Tag, _Tpl _Right): tuple(_Unpack_tuple_t{}, _STD forward_Tpl(_Right),make_index_sequencetuple_size_vremove_reference_t_Tpl{}) {}...//获取余下的元素类不带constconstexpr _Mybase _Get_rest() noexcept { // get reference to rest of elementsreturn *this;}//获取余下的元素类带constconstexpr const _Mybase _Get_rest() const noexcept { // get const reference to rest of elementsreturn *this;}...//template size_t _Index, class... _Typesfriend constexpr tuple_element_t_Index, tuple_Types... get(tuple_Types... _Tuple) noexcept;template size_t _Index, class... _Typesfriend constexpr const tuple_element_t_Index, tuple_Types... get(const tuple_Types... _Tuple) noexcept;template size_t _Index, class... _Typesfriend constexpr tuple_element_t_Index, tuple_Types... get(tuple_Types... _Tuple) noexcept;template size_t _Index, class... _Typesfriend constexpr const tuple_element_t_Index, tuple_Types... get(const tuple_Types... _Tuple) noexcept;template size_t _Index, class... _Typesfriend constexpr auto _Tuple_get(tuple_Types... _Tuple) noexcept;template class _Ty, class... _Typesfriend constexpr _Ty get(tuple_Types... _Tuple) noexcept;template class _Ty, class... _Typesfriend constexpr const _Ty get(const tuple_Types... _Tuple) noexcept;template class _Ty, class... _Typesfriend constexpr _Ty get(tuple_Types... _Tuple) noexcept;template class _Ty, class... _Typesfriend constexpr const _Ty get(const tuple_Types... _Tuple) noexcept;//包装的当前的元素类_Tuple_val_This _Myfirst; // the stored element }; 从上面的代码看到std::tuple的递归继承用到了private继承说明各个元素都是独立的互相没有关系。std::tuple的元素之间是一种组合的关系。另外一个是private继承可以造成empty base最优化这对致力于“对象尺寸最小化”的程序开发者而言可能很重要。 那么tuple是如何存储其中的元素呢 _Tuple_val_This _Myfirst; // the stored element 原来它有个成员叫_Myfirst它就是用来存储_This类型的变量的。你会看到_Myfirst的类型不是_This而是_Tuple_val_This其实_Tuple_val又是一个类模板它的代码这里就不展开了简而言之它的作用是存储一个tuple中的变量。_Myfirst._Val才是真正的元素。从_Tuple_val的定义可以看出 template class _Ty struct _Tuple_val { // stores each value in a tupleconstexpr _Tuple_val() : _Val() {}template class _Otherconstexpr _Tuple_val(_Other _Arg) : _Val(_STD forward_Other(_Arg)) {}template class _Alloc, class... _Other, enable_if_t!uses_allocator_v_Ty, _Alloc, int 0constexpr _Tuple_val(const _Alloc, allocator_arg_t, _Other... _Arg) : _Val(_STD forward_Other(_Arg)...) {}template class _Alloc, class... _Other,enable_if_tconjunction_v_STD uses_allocator_Ty, _Alloc,_STD is_constructible_Ty, _STD allocator_arg_t, const _Alloc, _Other...,int 0constexpr _Tuple_val(const _Alloc _Al, allocator_arg_t, _Other... _Arg): _Val(allocator_arg, _Al, _STD forward_Other(_Arg)...) {}template class _Alloc, class... _Other,enable_if_tconjunction_v_STD uses_allocator_Ty, _Alloc,_STD negation_STD is_constructible_Ty, _STD allocator_arg_t, const _Alloc, _Other...,int 0constexpr _Tuple_val(const _Alloc _Al, allocator_arg_t, _Other... _Arg): _Val(_STD forward_Other(_Arg)..., _Al) {}_Ty _Val; }; 在std::tuple类中定义_Myfirst的权限是public的所以对外面而言是直接访问元素值的。 通过上面的分析a中定义的类和类的继承关系图如下所示 class std::tuple; class std::tuplestd::string; class std::tupledouble, std::string; class std::tupleint, double, std::string; class std::tuplebool, int, double, std::string; 内存的分布图如下 2.std::tuple构造 tuple的构造函数就是初始化_Myfirst和_MyBase当然_MyBase也要进行么一个过程直到tuple。 //分类构造 template class _Tag, class _This2, class... _Rest2, enable_if_tis_same_v_Tag, _STD _Exact_args_t, int 0constexpr tuple(_Tag, _This2 _This_arg, _Rest2... _Rest_arg): _Mybase(_Exact_args_t{}, _STD forward_Rest2(_Rest_arg)...), _Myfirst(_STD forward_This2(_This_arg)) {}template class _Tag, class _Tpl, size_t... _Indices, enable_if_tis_same_v_Tag, _STD _Unpack_tuple_t, int 0constexpr tuple(_Tag, _Tpl _Right, index_sequence_Indices...);template class _Tag, class _Tpl, enable_if_tis_same_v_Tag, _STD _Unpack_tuple_t, int 0constexpr tuple(_Tag, _Tpl _Right): tuple(_Unpack_tuple_t{}, _STD forward_Tpl(_Right),make_index_sequencetuple_size_vremove_reference_t_Tpl{}) {}template class _Tag, class _Alloc, class _This2, class... _Rest2,enable_if_tis_same_v_Tag, _STD _Alloc_exact_args_t, int 0constexpr tuple(_Tag, const _Alloc _Al, _This2 _This_arg, _Rest2... _Rest_arg): _Mybase(_Alloc_exact_args_t{}, _Al, _STD forward_Rest2(_Rest_arg)...),_Myfirst(_Al, allocator_arg, _STD forward_This2(_This_arg)) {}template class _Tag, class _Alloc, class _Tpl, size_t... _Indices,enable_if_tis_same_v_Tag, _STD _Alloc_unpack_tuple_t, int 0constexpr tuple(_Tag, const _Alloc _Al, _Tpl _Right, index_sequence_Indices...);template class _Tag, class _Alloc, class _Tpl, enable_if_tis_same_v_Tag, _STD _Alloc_unpack_tuple_t, int 0constexpr tuple(_Tag, const _Alloc _Al, _Tpl _Right): tuple(_Alloc_unpack_tuple_t{}, _Al, _STD forward_Tpl(_Right),make_index_sequencetuple_size_vremove_reference_t_Tpl{}) {}//根据入口参数的不同分派到不同的构造函数 template class _This2, class... _Rest2,enable_if_tconjunction_v_STD _Tuple_perfect_valtuple, _This2, _Rest2...,_STD _Tuple_constructible_valtuple, _This2, _Rest2...,int 0constexpr explicit(_Tuple_conditional_explicit_vtuple, _This2, _Rest2...) tuple(_This2 _This_arg,_Rest2... _Rest_arg) noexcept(_Tuple_nothrow_constructible_vtuple, _This2, _Rest2...) // strengthened: tuple(_Exact_args_t{}, _STD forward_This2(_This_arg), _STD forward_Rest2(_Rest_arg)...) {}tuple(const tuple) default; tuple(tuple) default;tuple operator(const volatile tuple) delete; 它还提供了默认拷贝构造函数和移动构造函数移动语义是C11中新增的特性可以参考C之std::move(移动语义)-CSDN博客。其实它还有很多构造函数写起来挺热闹无非就是用不同的方式为它赋初值故省略。 上面的构造函数是根据_tag的不同被分派到不同的构造函数它叫标签派发。源码中定义了如下的标签 struct _Exact_args_t {explicit _Exact_args_t() default; }; // tag type to disambiguate construction (from one arg per element)struct _Unpack_tuple_t {explicit _Unpack_tuple_t() default; }; // tag type to disambiguate construction (from unpacking a tuple/pair)struct _Alloc_exact_args_t {explicit _Alloc_exact_args_t() default; }; // tag type to disambiguate construction (from an allocator and one arg per element)struct _Alloc_unpack_tuple_t {explicit _Alloc_unpack_tuple_t() default; }; // tag type to disambiguate construction (from an allocator and unpacking a tuple/pair) 3.std::tuple_size 先看一下源码 template class _Ty, _Ty _Val struct integral_constant {static constexpr _Ty value _Val;using value_type _Ty;using type integral_constant;constexpr operator value_type() const noexcept {return value;}_NODISCARD constexpr value_type operator()() const noexcept {return value;} };// TUPLE INTERFACE TO tuple template class... _Types struct tuple_sizetuple_Types... : integral_constantsize_t, sizeof...(_Types) {}; // size of tupletemplate class _Ty1, class _Ty2 struct tuple_sizepair_Ty1, _Ty2 : integral_constantsize_t, 2 {}; // size of pair std::integral_constant 包装特定类型的静态常量。它是 C 类型特征的基类。 std::tuple_size利用sizeof...求得可变参数的个数。 4.std::get访问值 先看一下tuple_elementtuple_element是获取tuple的元素包括_Myfirst和_MyBase源码 //tuple template size_t _Index struct _MSVC_KNOWN_SEMANTICS tuple_element_Index, tuple { // enforce bounds checkingstatic_assert(_Always_falseintegral_constantsize_t, _Index, tuple index out of bounds); };//tuple的_index 0 template class _This, class... _Rest struct _MSVC_KNOWN_SEMANTICS tuple_element0, tuple_This, _Rest... { // select first elementusing type _This;// MSVC assumes the meaning of _Ttype; remove or rename, but do not change semanticsusing _Ttype tuple_This, _Rest...; };//tuple的_index 0 template size_t _Index, class _This, class... _Rest struct _MSVC_KNOWN_SEMANTICS tuple_element_Index, tuple_This, _Rest...: tuple_element_Index - 1, tuple_Rest... {}; // recursive tuple_element definition//pair template size_t _Idx, class _Ty1, class _Ty2 struct _MSVC_KNOWN_SEMANTICS tuple_element_Idx, pair_Ty1, _Ty2 {static_assert(_Idx 2, pair index out of bounds);using type conditional_t_Idx 0, _Ty1, _Ty2; };template size_t _Index, class _Tuple using tuple_element_t typename tuple_element_Index, _Tuple::type; 通过_Index获取tuple元素 template size_t _Index, class... _Types _NODISCARD constexpr tuple_element_t_Index, tuple_Types... get(tuple_Types... _Tuple) noexcept {using _Ttype typename tuple_element_Index, tuple_Types...::_Ttype;return static_cast_Ttype(_Tuple)._Myfirst._Val; }template size_t _Index, class... _Types _NODISCARD constexpr const tuple_element_t_Index, tuple_Types... get(const tuple_Types... _Tuple) noexcept {using _Ttype typename tuple_element_Index, tuple_Types...::_Ttype;return static_castconst _Ttype(_Tuple)._Myfirst._Val; }template size_t _Index, class... _Types _NODISCARD constexpr tuple_element_t_Index, tuple_Types... get(tuple_Types... _Tuple) noexcept {using _Ty tuple_element_t_Index, tuple_Types...;using _Ttype typename tuple_element_Index, tuple_Types...::_Ttype;return static_cast_Ty(static_cast_Ttype(_Tuple)._Myfirst._Val); }template size_t _Index, class... _Types _NODISCARD constexpr const tuple_element_t_Index, tuple_Types... get(const tuple_Types... _Tuple) noexcept {using _Ty tuple_element_t_Index, tuple_Types...;using _Ttype typename tuple_element_Index, tuple_Types...::_Ttype;return static_castconst _Ty(static_castconst _Ttype(_Tuple)._Myfirst._Val); } 上述代码分析getindex的流程 1通过_Index递归构造出类 tuple_element_t 2)   获取当前元素 _MyFirst.Val 通过_Ty获取tuple元素 //辅助类 template class _Ty, class _Tuple struct _Tuple_element {}; // backstop _Tuple_element definitiontemplate class _This, class... _Rest struct _Tuple_element_This, tuple_This, _Rest... { // select first elementstatic_assert(!_Is_any_of_v_This, _Rest..., duplicate type T in getT(tuple));using _Ttype tuple_This, _Rest...; };template class _Ty, class _This, class... _Rest struct _Tuple_element_Ty, tuple_This, _Rest... { // recursive _Tuple_element definitionusing _Ttype typename _Tuple_element_Ty, tuple_Rest...::_Ttype; };//通过_Ty get template class _Ty, class... _Types _NODISCARD constexpr _Ty get(tuple_Types... _Tuple) noexcept {using _Ttype typename _Tuple_element_Ty, tuple_Types...::_Ttype;return static_cast_Ttype(_Tuple)._Myfirst._Val; }template class _Ty, class... _Types _NODISCARD constexpr const _Ty get(const tuple_Types... _Tuple) noexcept {using _Ttype typename _Tuple_element_Ty, tuple_Types...::_Ttype;return static_castconst _Ttype(_Tuple)._Myfirst._Val; }template class _Ty, class... _Types _NODISCARD constexpr _Ty get(tuple_Types... _Tuple) noexcept {using _Ttype typename _Tuple_element_Ty, tuple_Types...::_Ttype;return static_cast_Ty(static_cast_Ttype(_Tuple)._Myfirst._Val); }template class _Ty, class... _Types _NODISCARD constexpr const _Ty get(const tuple_Types... _Tuple) noexcept {using _Ttype typename _Tuple_element_Ty, tuple_Types...::_Ttype;return static_castconst _Ty(static_castconst _Ttype(_Tuple)._Myfirst._Val); } 上述代码分析get_Ty的流程 1通过_Ty递归构造出类 _Tuple_element 2)   获取当前元素 _MyFirst.Val 5.operator tuple重载了赋值符号这样tuple之间是可以赋值的。 tuple operator(const volatile tuple) delete;//以下是特殊情况是可以赋值的template class _Myself tuple, class _This2 _This,enable_if_tconjunction_v_STD _Is_copy_assignable_no_precondition_check_This2,_STD _Is_copy_assignable_no_precondition_check_Rest...,int 0_CONSTEXPR20 tuple operator(_Identity_tconst _Myself _Right) noexcept(conjunction_vis_nothrow_copy_assignable_This2, is_nothrow_copy_assignable_Rest...) /* strengthened */ {_Myfirst._Val _Right._Myfirst._Val;_Get_rest() _Right._Get_rest();return *this;}template class _Myself tuple, class _This2 _This,enable_if_tconjunction_v_STD _Is_move_assignable_no_precondition_check_This2,_STD _Is_move_assignable_no_precondition_check_Rest...,int 0_CONSTEXPR20 tuple operator(_Identity_t_Myself _Right) noexcept(conjunction_vis_nothrow_move_assignable_This2, is_nothrow_move_assignable_Rest...) {_Myfirst._Val _STD forward_This(_Right._Myfirst._Val);_Get_rest() _STD forward_Mybase(_Right._Get_rest());return *this;}template class... _Other, enable_if_tconjunction_v_STD negation_STD is_sametuple, _STD tuple_Other...,_STD _Tuple_assignable_valtuple, const _Other...,int 0_CONSTEXPR20 tuple operator(const tuple_Other... _Right) noexcept(_Tuple_nothrow_assignable_vtuple, const _Other...) /* strengthened */ {_Myfirst._Val _Right._Myfirst._Val;_Get_rest() _Right._Get_rest();return *this;}template class... _Other, enable_if_tconjunction_v_STD negation_STD is_sametuple, _STD tuple_Other...,_STD _Tuple_assignable_valtuple, _Other...,int 0_CONSTEXPR20 tuple operator(tuple_Other... _Right) noexcept(_Tuple_nothrow_assignable_vtuple, _Other...) /* strengthened */ {_Myfirst._Val _STD forwardtypename tuple_Other...::_This_type(_Right._Myfirst._Val);_Get_rest() _STD forwardtypename tuple_Other...::_Mybase(_Right._Get_rest());return *this;}template class _First, class _Second,enable_if_t_Tuple_assignable_vtuple, const _First, const _Second, int 0_CONSTEXPR20 tuple operator(const pair_First, _Second _Right) noexcept(_Tuple_nothrow_assignable_vtuple, const _First, const _Second) /* strengthened */ {_Myfirst._Val _Right.first;_Get_rest()._Myfirst._Val _Right.second;return *this;} 赋值符号返回左边的引用这种行为和C的内置类型是一致的。_Get_rest是tuple的成员函数作用是把除了_Myfirst之外的那些元素拿出来。 6._Equals //tuple内置函数template class... _Otherconstexpr bool _Equals(const tuple_Other... _Right) const {return _Myfirst._Val _Right._Myfirst._Val _Mybase::_Equals(_Right._Get_rest());}//重载operatortemplate class... _Types1, class... _Types2 _NODISCARD constexpr bool operator(const tuple_Types1... _Left, const tuple_Types2... _Right) {static_assert(sizeof...(_Types1) sizeof...(_Types2), cannot compare tuples of different sizes);return _Left._Equals(_Right); } 其中进行了静态断言如果两个tuple的元素个数不相同会引发一个编译时的错误。如果对应的类型不能用进行比较在模板特化时也会引发编译期的错误例如tuplestd::string, int不能和tupleint, char比较因为std::string和int是不能用进行比较的。 7.总结 终于写完了也是想了好久才写的涉及到的知识点主要是模版推导。写的不好的地方欢迎批评指正如果觉得好点个赞收藏关注
http://www.pierceye.com/news/108951/

相关文章:

  • 做php网站用什么软件开发wordpress页面图片轮播图
  • 做网站页面大小多大8上的信息课做网站作业
  • 自己做微网站创欧科技 网站建设
  • 网站设计师大学学什么专业北京燕华工程建设有限公司网站
  • 广州专业网站建设企业wordpress 数据库修改
  • 淮南装饰公司网站建设seo 网站树
  • 设计素材下载网站网络营销课程设计报告
  • 安庆公司做网站搜索引擎收录提交入口
  • 城固网站建设wordpress主题谁的最好
  • 国外建站企业北京鑫创网站建设
  • 网站做视频wordpress插件手动升级
  • wordpress收不到网站没有收款接口网站怎么做收款
  • 信阳做网站推广用tornado做网站
  • 网站开发与数据库ppt成都优化网站建设
  • 毕业设计静态网站建设选题依据企业网络营销的优势
  • 网站图片动态换名网站充值支付宝收款怎么做
  • 蜘蛛网是个什么网站做特卖的购物网站
  • 从零学做网站古典 网站模板
  • h5网站模板开发网站后台哪些功能需要前端配合
  • 网站建设 宜宾佛山企业网站自助建站
  • 苏宁易购网站建设 的定位手机网站制作招聘
  • 个人网站备案申请360老是提示危险网站
  • 建网站哪个好 优帮云自己怎么注册域名
  • 做3ds磁铁卡网站大连旅顺博物馆
  • 邢台市住房和城乡建设局网站大连网站推广机构
  • 网站建设开标书房地产网页设计
  • 中国建设建设工程造价管理协会网站建设视频网站要求吗
  • 商务网站教程深圳定制纸箱
  • 湖南手机版建站系统哪家好自己做网站地图
  • 天津网站制作报价阿里云需要网站建设方案书