返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++中traits技术的示例分析
  • 908
分享到

C++中traits技术的示例分析

2023-06-15 07:06:01 908人浏览 薄情痞子
摘要

这篇文章主要介绍了c++中traits技术的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Traits编程技法  让我们一点点抛出问题,然后一点点深入。  1. 首先

这篇文章主要介绍了c++中traits技术的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

Traits编程技法

  让我们一点点抛出问题,然后一点点深入。

  1. 首先,在算法中运用迭代器时,很可能会用到其相应型别(迭代器所指之物的型别)。假设算法中有必要声明一个变量,以“迭代器所指对象的型别”为型别,该怎么办呢?

  解决方法是:利用function template的参数推导机制。

template <class I, class T>void func_impl(I iter, T t) {        T tmp; // 这里就是迭代器所指物的类型新建的对象        // ... 功能实现}template <class I>inlinevoid func(I iter) {        func_impl(iter, *iter); // 传入iter和iter所指的值,class自动推导}int main() {    int i;    func(&i);}

  这里已经可以看出封装的意思了,没有一层impl的封装的话,每次你都要显式地说明迭代器指向对象型别,才能新建tmp变量。加一层封装显得清爽很多。

  迭代器相应型别不只是“迭代器所指对象的型别”一种而已。根据经验,最常用的相应型别有五种,然而并非任何情况下任何一种都可以利用上述的template参数推导机制来取得。

  函数的“template参数推导机制”推导的只是参数,无法推导函数的返回值类型。万一需要推导函数的传回值,就无能为力了。

  2. 声明内嵌型别似乎是个好主意,这样我们就可以直接获取。

template <class T>struct MyIter {    typedef T value_type; // 内嵌型别声明    // ...};template <class I>typename I::value_typefunc(I ite) {    return *ite;}// ...MyIter<int> ite(new int(8));cout << func(ite);

  看起来不错,但是并不是所有迭代器都是class type,原生指针就不行!如果不是class type,就无法为它定义内嵌型别。

  这时候就需要 偏特化 出现。

  3. 偏特化就是在特化的基础上再加一点限制,但它还是特化的template。

 template <class I>  struct iterator_traits {      typedef typename I::value_type value_type;  };    template <class I>  struct iterator_traits<T*> {      typedef T value_type;  };  template <class I>12 typename iterator_traits<I>::value_type func(I ite) {     return *ite; }

  func在调用 I 的时候,首先把 I 传到萃取器中,然后萃取器就匹配最适合的 value_type。(萃取器会先匹配最特别的版本)这样当你传进一个原生指针的时候,首先匹配的是带<T*>的偏特化版本,这样 value_type 就是 T,而不是没有事先声明的 I::value_type。这样返回值就可以使用 typename iterator_traits<I>::value_type 来知道返回类型。

  下面附上《STL源码剖析》的图片:

C++中traits技术的示例分析

让traits干更多东西

  迭代器有常见有五种类型: value_type, difference_type, reference_type, pointer_type都比较容易在 traits 和 相应偏特化中提取。但是,iterator_cateGory一般也有5个,这个相应型别会引发较大规模的写代码工程。

  例如,我们实现了 func_II, func_BI, func_RAI 分别代表迭代器类型是Input Iterator,Bidirectional Iterator和Random Access Iterator的对应实现。

  现在,当客端调用func()的时候,我们可能需要做一个判断:

template<class Iterator>void func(Iterator& i) {    if (is_random_access_iterator(i))        func_RAI(i);    if (is_bidirectional_iterator(i))        func_BI(i);    else        func_II(i);}

  但这样在执行时期才决定使用哪一个版本,会影响程序效率。最好能够在编译期就选择正确的版本。

  重载这个函数机制可以达成这个目标。

struct input_iterator_tag {}; struct output_iterator_tag {};struct forward_iterator_tag : public input_iterator_tag {}; // ... // 继承的好处就是,当函数需要用 input_iterator_tag 的时候// 假设你传进一个forward_iterator_tag,它会沿继承向上找,知道符合条件

  声明了一些列 tag 之后,我们就可以重载 func函数: func(tag)。

  到这里,各个型别的具体重载实现已经写好,但是需要一个统一的接口,这时候 traits 就可以出场了。

template<class Iterator> inline void func(Iterator& i) {    typedef typename Iterator_traits<Iterator>::iterator_category category;    __func(i, category()); // 各型别的重载 }

简单实例代码

  所以说,traits一方面,在面对不同的输入类时,能找到合适的返回型别;另一方面,当型别对应有不同的实现函数的时候,能起到一个提取型别然后分流的作用。

  先假设我们有一个 func 函数,可以接受 自定义的类 或者 原始的指针 作为参数,并自动输出使用了什么tag。

  首先根据 traits(由本身或偏特化版本实现) ,它会提取 u 的返回型别,然后调用对应的构造函数 return_type(), 来当作各个重载版本 __func 的重载标志区分不同的实际函数。

  C++中traits技术的示例分析

首先我们看看接口代码的编写

 template <class unknown_class> inline typename unknown_class_traits<unknown_class>::return_type // 萃取器取得对应型别 func(unknown_class u) {     typedef typename unknown_class_traits<unknown_class>::return_type return_type;     return __func(u, return_type()); // 需要调用构造函数当tag }

然后是实现设定的 tag ,用来模仿前面说的 II,RAI等

 template <class unknown_class> inline typename unknown_class_traits<unknown_class>::return_type return_type(unknown_class) {     typedef typename unknown_class_traits<unknown_class>::return_type RT;     return RT(); }

有了这些我们就可以测试

struct A {};struct B : A{};

然后是 traits 隆重登场,有两个偏特化版本。

template <class unknown_class>struct unknown_class_traits {    typedef typename unknown_class::return_type return_type;};template <class T>struct unknown_class_traits<T*> {    typedef T return_type;};template <class T>struct unknown_class_traits<const T*> {    typedef const T return_type;};

突然忘记了交代 unknown_class 的结构,自定义的类,必须要 typedef。

 template <class AorB>struct unknown_class {   typedef AorB return_type;};

最后是func各个重载版本。

template <class unknown_class>inline typename unknown_class_traits<unknown_class>::return_type__func(unknown_class, A) {    cout << "use A flag" << endl;    return A();}template <class unknown_class>inline typename unknown_class_traits<unknown_class>::return_type__func(unknown_class, B) {    cout << "use B flag" << endl;    return B();}template <class unknown_class, class T>T__func(unknown_class, T) {    cout << "use origin ptr" << endl;    return T();}

有了这些我们就可以测试了

int main() {    unknown_class<B> b;    unknown_class<A> a;    //unknown_class<int> i;    int value = 1;    int *p = &value;    A v1 = func(a);    B v2 = func(b);    int v3 = func(p);    char ch = getchar();}

  可以看到,对于用自定义类传入同一个接口,它会自动使用对应的函数,而且返回值也合适。对原始指针也适用,完美!

C++中traits技术的示例分析

下面是完整代码:

#include <iOStream>using namespace std;struct A {};struct B : A{}; // 继承的好处就是,当函数需要参数为A,                // 而你传入的参数为B的时候,可以往上一直找到适合的对象template <class AorB>struct unknown_class {    typedef AorB return_type;};template <class unknown_class>struct unknown_class_traits {    typedef typename unknown_class::return_type return_type;};template <class T>struct unknown_class_traits<T*> {    typedef T return_type;};template <class T>struct unknown_class_traits<const T*> {    typedef const T return_type;};template <class unknown_class>inline typename unknown_class_traits<unknown_class>::return_typereturn_type(unknown_class) {    typedef typename unknown_class_traits<unknown_class>::return_type RT;    return RT();}template <class unknown_class>inline typename unknown_class_traits<unknown_class>::return_type__func(unknown_class, A) {    cout << "use A flag" << endl;    return A();}template <class unknown_class>inline typename unknown_class_traits<unknown_class>::return_type__func(unknown_class, B) {    cout << "use B flag" << endl;    return B();}template <class unknown_class, class T>T__func(unknown_class, T) {    cout << "use origin ptr" << endl;    return T();}template <class unknown_class>inline typename unknown_class_traits<unknown_class>::return_typefunc(unknown_class u) {    typedef typename unknown_class_traits<unknown_class>::return_type return_type;    return __func(u, return_type());}int main() {    unknown_class<B> b;    unknown_class<A> a;    //unknown_class<int> i;    int value = 1;    int *p = &value;    A v1 = func(a);    B v2 = func(b);    int v3 = func(p);    char ch = getchar();}

感谢你能够认真阅读完这篇文章,希望小编分享的“C++中traits技术的示例分析”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网其他教程频道,更多相关知识等着你来学习!

--结束END--

本文标题: C++中traits技术的示例分析

本文链接: https://www.lsjlt.com/news/278535.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C++中traits技术的示例分析
    这篇文章主要介绍了C++中traits技术的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Traits编程技法  让我们一点点抛出问题,然后一点点深入。  1. 首先...
    99+
    2023-06-15
  • 深入浅析C++ traits技术
    前言   traits,又被叫做特性萃取技术,说得简单点就是提取“被传进的对象”对应的返回类型,让同一个接口实现对应的功能。因为STL的算法和容器是分离的,两者通过迭代器链接。算法的...
    99+
    2024-04-02
  • mongodb分片技术的示例分析
    这篇文章主要为大家展示了“mongodb分片技术的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“mongodb分片技术的示例分析”这篇文章吧。在mong...
    99+
    2024-04-02
  • Hybrid App技术的示例分析
    这篇文章给大家分享的是有关Hybrid App技术的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。背景随着Web技术的发展和移动互联网的发展,Hybrid技术已经成为一种...
    99+
    2024-04-02
  • Css技术中height属性的示例分析
    这篇文章主要介绍了Css技术中height属性的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、height1、height:10...
    99+
    2024-04-02
  • 区块链技术的示例分析
    这篇文章给大家分享的是有关区块链技术的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。区块链技术最初源于解决“拜占庭将军”问题,金融科技的发展使得区块链技术有了更好的应用场...
    99+
    2024-04-02
  • ajax请求技术的示例分析
    这篇文章主要为大家展示了“ajax请求技术的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“ajax请求技术的示例分析”这篇文章吧。1.写在前面:阅读要求...
    99+
    2024-04-02
  • Redis主从技术的示例分析
    这篇文章主要为大家展示了“Redis主从技术的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Redis主从技术的示例分析”这篇文章吧。Redis复制在生产环境中,Redis通过持久化功能...
    99+
    2023-06-27
  • Hadoop技术创新的示例分析
    这篇文章将为大家详细讲解有关Hadoop技术创新的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。如今有很多公司都在努力挖掘他们拥有的大量数据,包括结构化、非结构化、半结构化以及二进制数据等,来探索...
    99+
    2023-06-02
  • SEO优化技术的示例分析
    这篇文章给大家分享的是有关SEO优化技术的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。如何设置SEO关键词当然重要,但SEO优化技术如果只是机械式的说该做什麽不做什麽,而涉及的步骤又非常死板,例如:将焦...
    99+
    2023-06-10
  • Css技术中线性渐变的示例分析
    小编给大家分享一下Css技术中线性渐变的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!对象选择器 {background...
    99+
    2024-04-02
  • JavaWeb之会话技术的示例分析
    这篇文章给大家分享的是有关JavaWeb之会话技术的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。会话技术    1. 会话:一次会话中包含多次请求和响应...
    99+
    2023-06-20
  • 数据库恢复技术的示例分析
    小编给大家分享一下数据库恢复技术的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!数据库恢复...
    99+
    2024-04-02
  • Linux虚拟化技术KVM的示例分析
    这篇文章主要介绍Linux虚拟化技术KVM的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!KVM是一种内建于 Linux&reg; 中的开源虚拟化技术。具体而言,KVM 可帮助您将 Linux 转变为...
    99+
    2023-06-27
  • Ajax技术中servlet末尾输出流的示例分析
    这篇文章主要介绍Ajax技术中servlet末尾输出流的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Ajax的服务器端用PrintWriter out=resp.getWr...
    99+
    2024-04-02
  • python字符串驻留技术的示例分析
    小编给大家分享一下python字符串驻留技术的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!前言每种编程语言为了表现出色,并且实现卓越的性能,都需要有大量...
    99+
    2023-06-15
  • TH-OCR文字识别技术的示例分析
    这篇文章主要为大家展示了“TH-OCR文字识别技术的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“TH-OCR文字识别技术的示例分析”这篇文章吧。随着信息流技术、多媒体技术的飞速发展,以...
    99+
    2023-06-02
  • JVMCPUProfiler技术原理及源码的示例分析
    JVMCPUProfiler技术原理及源码的示例分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。引言研发人员在遇到线上报警或需要优化系统性能时,常常需要分析程...
    99+
    2023-06-03
  • 证书锁定Certificate Pinning技术的示例分析
    这篇文章主要介绍了证书锁定Certificate Pinning技术的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。证书锁定Certificate Pinning技术...
    99+
    2023-06-04
  • ADO.NET技术举例分析
    这篇文章主要介绍“ADO.NET技术举例分析”,在日常操作中,相信很多人在ADO.NET技术举例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”ADO.NET技术举例分析”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作