boost学习 内嵌类型 与 any 的代码联系

本文是学习 boost源码的一些练习

参考文章来自

刘未鹏

C++的罗浮宫(http://blog.csdn.net/pongba)

目录

http://blog.csdn.net/pongba/article/category/37521

检测内嵌类型

检测一个类中是否存在指定的类型

那么只需要利用模板检测输入参数 根据参数的不同 导入到不同的函数中

类似

 template <typename T>
 void Register(T person)
 {
     Register(person, typename T::person_tag());
 }
    struct student_tag {};
 16 struct teacher_tag {};
 17
 18 template<typename T>
 19 void Register(T p,student_tag) {
 20     std::cout << __FUNCTION__  << " student_tag"<< std::endl;
 21 }
 22
 23 template<typename T>
 24 void Register(T p, teacher_tag) {
 25     std::cout << __FUNCTION__ << " teacher_tag"<<std::endl;
 26 }那么只要输入的参数含有这个tag结构 就会输入到不同的函数中 这是stl经常使用的套路

另外一种需求是检测类中是否带有指定的type 而不是如上所述 要事先在类中定义好tag比如我们要检测任意类型中是否有我们需要关注的key_type定义如下
 36 typedef char(&yes_type)[1]; // sizeof(yes_type)==1
 37 typedef char(&no_type)[2]; // sizeof(no_type)==2
 38
 39 template<class T>
 40 struct does_sometypedef_exists
 41 {
 42     template<class U>
 43     static yes_type check(U, typename U::key_type* = nullptr); // #1
 44     static no_type check(...);
 45     static T t;   // 声明
 46     static const bool value = sizeof(check(t)) == sizeof(yes_type);
 47 };根据模板特性 如果输入的参数U 带有key_type 则check函数是该形式
static yes_type check(U, typename U::key_type* = nullptr);返回 yes_type

输入参数U是其他类型 则check形式如下
 static no_type check(...);返回 no_type

根据定义 no_type yes_type长度不同那么只需要检测check函数的返回长度 就可以确认输入的参数U是否带有key_type
static const bool value = sizeof(check(t)) == sizeof(yes_type);我们查看下
does_sometypedef_exists<T>::type 是否为真就能确认T是否包含key_type

//================================================================================

同样的利用模板偏特化及默认模板参数的规则也可以实现根据输入类型T是否包含key_type 适配不同版本代码

template<class T,class>

struct check_helper

{

typedef T type;

};

template<class T,class =T>

struct does_sometypedef_exists_1

{

static const bool value=false;

};

template<class T>

struct does_sometypedef_exists_1<T,

typename check_helper<T, typename T::key_type>::type>

{

static const bool value=true;

};

完整代码如下

  1 // Study1.cpp: 定义控制台应用程序的入口点。
  2 //
  3
  4 #include "stdafx.h"
  5 #include <string>
  6 #include <iostream>
  7
  8
  9 template <typename T>
 10 void Register(T person)
 11 {
 12     Register(person, typename T::person_tag());
 13 }
 14
 15 struct student_tag {};
 16 struct teacher_tag {};
 17
 18 template<typename T>
 19 void Register(T p,student_tag) {
 20     std::cout << __FUNCTION__  << " student_tag"<< std::endl;
 21 }
 22
 23 template<typename T>
 24 void Register(T p, teacher_tag) {
 25     std::cout << __FUNCTION__ << " teacher_tag"<<std::endl;
 26 }
 27
 28 void ModelInSTL() {
 29     std::string person;
 30     student_tag s;
 31     teacher_tag t;
 32     Register(person, s);
 33     Register(person, t);
 34 }
 35 //=========================================================
 36 typedef char(&yes_type)[1]; // sizeof(yes_type)==1
 37 typedef char(&no_type)[2]; // sizeof(no_type)==2
 38
 39 template<class T>
 40 struct does_sometypedef_exists
 41 {
 42     template<class U>
 43     static yes_type check(U, typename U::key_type* = nullptr); // #1
 44     static no_type check(...);
 45     static T t;   // 声明
 46     static const bool value = sizeof(check(t)) == sizeof(yes_type);
 47 };
 48
 49 struct A {};
 50 struct B
 51 {
 52     typedef int key_type;
 53 };
 54
 55 // key_type为成员函数
 56 struct C { void key_type(void) {} };
 57
 58 // key_type为静态常量数据成员
 59 struct D { static const bool key_type = false; };
 60
 61 struct E {
 62     struct key_type
 63     {};
 64 };
 65
 66 //==============================================================
 67
 68 template<class T, class>
 69 struct check_helper
 70 {
 71     typedef T type;
 72 };
 73
 74 template<class T, class = T>
 75 struct does_sometypedef_exists_1
 76 {
 77     static const bool value = false;
 78 };
 79
 80 template<class T>
 81 struct does_sometypedef_exists_1<T,
 82     typename check_helper<T, typename T::key_type>::type>
 83 {
 84     static const bool value = true;
 85 };
 86
 87 //=========================================================
 88
 89
 90 int main()
 91 {
 92     ModelInSTL();
 93     std::cout << does_sometypedef_exists<A>::value << std::endl;
 94     std::cout << does_sometypedef_exists<B>::value << std::endl;
 95     std::cout << does_sometypedef_exists<C>::value << std::endl;
 96     std::cout << does_sometypedef_exists<D>::value << std::endl;
 97     std::cout << does_sometypedef_exists<E>::value << std::endl;
 98     std::cout << std::endl;
 99     std::cout << does_sometypedef_exists_1<A>::value << std::endl;
100     std::cout << does_sometypedef_exists_1<B>::value << std::endl;
101     std::cout << does_sometypedef_exists_1<C>::value << std::endl;
102     std::cout << does_sometypedef_exists_1<D>::value << std::endl;
103     std::cout << does_sometypedef_exists_1<E>::value << std::endl;
104
105     return 0;
106 }


ANY

BOOST中有一个ANY类

可以接受任意类型的输入

示例如下

11 #include <boost/any.hpp>
 12 #include <list>
 13 #include <exception>
 14 #include <memory>
 15 //
 16 //class AClass {};
 17 //
 18 //void BOOSTAnySample()
 19 //{
 20 //    typedef std::list<boost::any> many;
 21 //    //any可存入任何类型
 22 //    many values;
 23 //    boost::any value = 1;
 24 //    values.push_back(value);
 25 //
 26 //    value = "string";
 27 //    values.push_back(value);
 28 //
 29 //    values.push_back(true);
 30 //    values.push_back(nullptr);
 31 //    values.push_back(AClass());
 32 //}

根据使用方式 any不能定义模板 因为我们不可能使用any<int> a = 1; 那同定义 int a = 1就没区别了所以any类中肯定有一个与输入类型相同的元素进行存储

  1 // UseRapidJsonSample.cpp: 定义控制台应用程序的入口点。
  2 //
  3
  4 #include "stdafx.h"
  5 #include <iostream>
  6 #include <string>
  7 #include "JsonStringTool.h"
  8 #include "rapidjson/writer.h"
  9 #include "rapidjson/stringbuffer.h"
 10 #include "rapidjson/document.h"
 11 #include <boost/any.hpp>
 12 #include <list>
 13 #include <exception>
 14 #include <memory>
 15 //
 16 //class AClass {};
 17 //
 18 //void BOOSTAnySample()
 19 //{
 20 //    typedef std::list<boost::any> many;
 21 //    //any可存入任何类型
 22 //    many values;
 23 //    boost::any value = 1;
 24 //    values.push_back(value);
 25 //
 26 //    value = "string";
 27 //    values.push_back(value);
 28 //
 29 //    values.push_back(true);
 30 //    values.push_back(nullptr);
 31 //    values.push_back(AClass());
 32 //}
 33 //===========================================================
 34 class any
 35 {
 36 public:
 37
 38     class placeholder // 泛型数据容器holder的非泛型基类
 39     {
 40     public:
 41         // 虚析构函数,为保证派生类对象能用基类指针析构
 42         virtual ~placeholder() {}
 43
 44     public:
 45         // 提供关于类型的信息
 46         virtual const std::type_info & type() const = 0;
 47         virtual placeholder * clone() const = 0;  // 复制
 48     }; // placeholder
 49
 50     template<typename ValueType>
 51     class holder : public placeholder
 52     {
 53     public:
 54         holder(const ValueType & value)
 55             : held(value)
 56         {}
 57     public:
 58         virtual const std::type_info & type() const
 59         {
 60             // typeid返回std::typeinfo对象引用,后者包含任意对象的类型信息, 如name,此外还提供operator==操作符你可以用typeid(oneObj)==typeid(anotherObj)来比两个对象之类型是否一致。
 61             return typeid(ValueType);
 62         }
 63
 64         virtual placeholder * clone() const
 65         {
 66             return new holder(held);  // 改写虚函数,返回自身的复制体
 67         }
 68
 69     public:
 70         ValueType held; // 数据保存的地方
 71     }; // holder
 72
 73        // 指向泛型数据容器holder的基类placeholder的指针
 74     placeholder * content;
 75
 76     //模板构造函数,动态分配数据容器并调用其构造函数
 77     template<typename ValueType>
 78     any(const ValueType & value)
 79         : content(new holder<ValueType>(value))
 80     {}
 81
 82         // 与模板构造函数一样,但使用了swap惯用手法
 83         template<typename ValueType>
 84     any & operator=(const ValueType & rhs)
 85     {
 86         // 先创建一个临时对象any(rhs),再调用下面的swap函数进行底层数据交换,注意与*this交换数据的是临时对象,所以rhs的底层数据并未被更改,只是在swap结束后临时对象拥有了*this的底层数据,而此时*this也拥有了临时对象构造时所拥有的rhs的数据的副本。然后临时对象由于生命期的结束而被自动析构,*this原来的底层数据随之烟消云散。
 87         any(rhs).swap(*this);
 88         return *this;
 89     }
 90
 91     any & swap(any & rhs) //swap函数,交换底层数据
 92     {
 93         std::swap(content, rhs.content); // 只是简单地将两个指针的值互换
 94         return *this;
 95     }
 96
 97     ~any()  //析构函数
 98     {
 99         //释放容器,用的是基类指针,这就是placeholder需要一个虚析构函数的原因
100         delete content;
101     }
102
103 };
104 //
105 template<typename ValueType>
106 ValueType * any_cast(const any * operand)
107 {
108     // 这个类型检查很重要,后面会对它作更详细的解释
109     return
110         operand &&
111         (operand->content->type() == typeid(ValueType)) ? // #1
112         &((static_cast<any::holder<ValueType>*>(operand->content))->held)
113         : 0; // 这儿有个向下类型转换
114 }
115
116
117 template<typename ValueType>
118 ValueType any_cast(const any & operand)
119 {
120     //// 调用any_cast针对指针的版本。
121
122     const ValueType * result = any_cast<ValueType>(&operand);
123
124     // 如果cast失败,即实际 保存的并非ValueType型数据,则抛出一个异常。
125     if (!result)
126         throw std::exception("bad alloc"); // 派生自std::bad_cast
127     return *result;
128 }
129
130
131 int main()
132 {
133
134     any ai(1);
135     int i = any_cast<int>(ai);
136     std::cout << i << std::endl;
137
138     any ad(3.12222222222222222);
139     double d = any_cast<double>(ad);
140     std::cout << d << std::endl;
141
142     any ab(true);
143     bool b = any_cast<bool>(ab);
144     std::cout << b << std::endl;
145
146     any ac(‘z‘);
147     char c = any_cast<char>(ac);
148     std::cout << c << std::endl;
149
150     return 0;
151 }

时间: 2024-08-28 22:14:38

boost学习 内嵌类型 与 any 的代码联系的相关文章

Selenium-测试对象操作之:多窗口、内嵌frame

操作策略:通过selenium提供的方法切换后进行操作 窗口切换:switch_to_window() frame切换:switch_to_frame 窗口切换注意:窗口打开顺序和窗口句柄列表索引的关系 页面打开顺序:1 2 3   窗口句柄索引:0 2 1 多窗口案例: #coding=utf-8from selenium import webdriverimport time,os driver = webdriver.Chrome()driver.get("https://www.hao1

Elastic search中使用nested类型的内嵌对象

在大数据的应用环境中,往往使用反范式设计来提高读写性能. 假设我们有个类似简书的系统,系统里有文章,用户也可以对文章进行赞赏.在关系型数据库中,如果按照数据库范式设计,需要两张表:一张文章表和一张赞赏历史记录表,赞赏历史记录表包括了赞赏者姓名和赞赏金额. 在Elastic search中,由于都是json格式存储,则可以在一个index存储系统中的文章及其赞赏记录,这种情况下需要在elastic search中使用nested类型的内嵌对象.因为如果使用数组或者object对象的话,赞赏者姓名和

Android学习之——如何将GridView内嵌在ScrollView中

最近在做一个项目,有一个需求是在ScrollView中内嵌一个GridView. 刚开始,我是以为能直接内嵌在里面: 1 <ScrollView 2 android:layout_width="match_parent" 3 android:layout_height="0dp" 4 android:layout_weight="5.5"> 5 <GridView 6 android:id="@+id/gridView

前端学习 第二天 块与内嵌关系

块的特征 (代表div) 1.默认独占一行默认独占一行 2.没有宽度时,默认撑满一排 3.支持所有css命令 内嵌(内联.行内)的特征(span) 1.同排可以继续跟同类的标签 2.内容撑开宽度 3.不支持宽高 4.不支持上下的margin 5.代码换行被解析 display:block 显示为块 使内联元素具备块属性标签的特性 display:inline 显示为内嵌 使行块属性标签具备内联元素的特性 inline-block的特点 特性: 1.块在一行显示: 2.行内属性标签支持宽高: 3.

Ok6410裸机驱动学习(三)C语言内嵌汇编

1.C语言内嵌汇编使用方法 C内嵌汇编以关键字”_asm_或asm开始,下辖4个部分,各部分之间用“:”分开,第一部分是必须写的,后面3个部分可以省略,但是分号:不能省略 优化后的代码 2.汇编程序框架 .section .data <初始化的数据> .section .bss <未初始化的数据> .section .text .global _start _start: <汇编代码>

【MongoDB学习笔记18】MongoDB的查询:find查询内嵌文档

查询内嵌文档和查询普通文档完全相同: 例如: > db.post.find()    { "_id" : ObjectId("54ace1394ba07ed75df68f90"), "name" : { "firstname" : "joe", "lastname" : "schome" }, "age" : 28 }     { "

学习MongoDB 五: MongoDB查询(数组、内嵌文档)(二)

一.简介 我们上一篇介绍了db.collection.find()可以实现根据条件查询和指定使用投影运算符返回的字段省略此参数返回匹配文档中的所有字段,我们今天介绍了对数组和内嵌文档的查询操作,尤其是对$elemMatch 同样可以用在find方法的第二个参数来限制返回数组内的元素,只返回我们需要的文档的介绍.我们经常在查询条件查询内嵌文档数组时,只需要返回主文档并返回内嵌文档数组中我们只需要的值,而不是把内嵌文档的数组都返回. 二.对数组根据条件查询  $all.$size.$slice.$e

Python 学习笔记 -- 内嵌函数、闭包、匿名函数、高阶函数map、高阶函数filter、高阶函数reduce

1 #------------------------------内嵌函数------------------------------ 2 #内嵌函数就是在函数内部定义函数 3 #实例一 4 print("#------------------------------内嵌函数------------------------------") 5 def funOutOne(): 6 x = 5 7 def funIn(): 8 x = 3 9 print("My funOutO

GCC在C语言中内嵌汇编 asm __volatile__ 【转】

转自:http://blog.csdn.net/pbymw8iwm/article/details/8227839 在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器,以及如何将计算结果写回C 变量,你只要告诉程序中C语言表达式与汇编指令操作数之间的对应关系即可, GCC会自动插入代码完成必要的操作. 1.简单的内嵌汇编 例: __asm__ __volatile__("hlt"); "__asm__"表示后面的