本文是学习 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-10-28 10:47:10