将N层集合对象自动转化为对应的.NET泛型对象(C++)
来源:互联网 发布:mac media player加速 编辑:程序博客网 时间:2024/05/21 11:37
昨天别人碰到的问题,晚上回来想了一下给出了一个用模板进行类型推导的解决方案。
问题本身需求很清楚,就是需要写一个Util函数,将C++里面的那些模板(template)集合对象自动转换成.NET里面的泛型(Generic)集合对象,比如将vector<int>转化成List<int>^。因为类型(Type)不定,所以用模板来进行转化是不二的选择。问题的难点在于这些集合类还可以是嵌套类型,也就是说集合里面装的还是集合(比如将vector<vector<int> >转化成List<List<int>^>^),甚至还得考虑多层集合嵌套的情况。
- // NativeToManagedTypeApp.cpp : main project file.
- // author: Anders Deng
- // date: 2008/8/29
- #include "stdafx.h"
- #include <vector>
- using namespace System;
- using namespace System::Collections::Generic;
- using namespace std;
- // for method overload
- struct __true__value {};
- struct __false__value{};
- // some classes for type traits
- template<class T>
- struct collection_Type_Traits
- {
- typedef __false__value isCollection;
- typedef T __template__param__type;
- };
- template<typename T>
- struct collection_Type_Traits<std::vector<T> >
- {
- typedef __true__value isCollection;
- typedef T __template__param__type;
- };
- template<class T>
- struct collection_Type_Traits<List<T>^ >
- {
- typedef __true__value isCollection;
- typedef T __template__param__type;
- };
- // add more specialization template definition
- // ...
- template<class T>
- struct managed_Type_Traits
- {
- typedef __false__value isValueType;
- typedef T param_type_name;
- };
- template<class T>
- struct managed_Type_Traits<T^>
- {
- typedef __false__value isValueType;
- typedef T param_type_name; // remove ^ from reference type
- };
- template<>
- struct managed_Type_Traits<int>
- {
- typedef __true__value isValueType;
- typedef int param_type_name;
- };
- // add more specialization template definition for other required value class
- // ...
- public ref class Util
- {
- public:
- template<class NativeType, class ManagedType>
- static ManagedType nativeToManaged(NativeType nativeObj)
- {
- return __nativeToManaged<NativeType, ManagedType>(nativeObj, collection_Type_Traits<NativeType>::isCollection(), managed_Type_Traits<ManagedType>::isValueType());
- }
- private:
- // collection && reference type
- template<class NativeType, class ManagedType>
- static ManagedType __nativeToManaged(NativeType nativeObj, __true__value, __false__value)
- {
- ManagedType list = gcnew managed_Type_Traits<ManagedType>::param_type_name();
- for (NativeType::iterator it = nativeObj.begin(); it != nativeObj.end(); ++it)
- {
- typedef collection_Type_Traits<NativeType>::__template__param__type InternalNativeType;
- typedef collection_Type_Traits<ManagedType>::__template__param__type InternalManagedType;
- list->Add(__nativeToManaged<InternalNativeType, InternalManagedType>(*it, collection_Type_Traits<InternalNativeType>::isCollection(), managed_Type_Traits<InternalManagedType>::isValueType()));
- }
- return list;
- }
- // non-collection && reference type
- template<class NativeType, class ManagedType>
- static ManagedType __nativeToManaged(NativeType nativeObj, __false__value, __false__value)
- {
- return gcnew managed_Type_Traits<ManagedType>::param_type_name(nativeObj.c_str());
- }
- // non-collection && reference type
- template<class NativeType, class ManagedType>
- static ManagedType __nativeToManaged(NativeType nativeObj, __false__value, __true__value)
- {
- return nativeObj;
- }
- };
- int main(array<System::String ^> ^args)
- {
- // ----------------------------------
- // test vector<int> => List<int>^
- // ----------------------------------
- vector<int> intV;
- intV.push_back(4);
- intV.push_back(5);
- List<int>^ l = Util::nativeToManaged<vector<int>, List<int>^>(intV);
- for each(int i in l)
- {
- Console::Write("{0} ", i);
- }
- Console::WriteLine();
- // ----------------------------------
- // test vector<vector<int>> => List<List<int>^>^
- // ----------------------------------
- vector<vector<int>> iVV;
- vector<int> iV;
- iV.push_back(1);
- iV.push_back(2);
- iVV.push_back(iV);
- List<List<int>^ >^ list = Util::nativeToManaged<vector<vector<int> >, List<List<int>^>^ >(iVV);
- for each(List<int>^ l in list)
- {
- for each(int i in l)
- Console::Write("{0} ", i);
- Console::WriteLine();
- }
- // ---------------------------------
- // test vector<vector<string>> => List<List<String^>^>^
- // ---------------------------------
- vector<string> sV;
- vector<vector<string>> sVV;
- sV.push_back("abc");
- sV.push_back("def");
- sV.push_back("ghi");
- sVV.push_back(sV);
- List<List<String^>^>^ sll = Util::nativeToManaged<vector<vector<std::string>>, List<List<String^>^>^>(sVV);
- for each(List<String^>^ sl in sll)
- {
- for each(String^ s in sl)
- Console::Write("{0} ", s);
- Console::WriteLine();
- }
- return 0;
- }
代码如上,就不多解释了。关于type traits可以参考这篇文章,关于特化(specialization)、偏特化(partial specialization)的文章可以看侯捷先生的《STL源码分析》。需要特别指出的是,虽然.NET的Generic原理上不支持特化和偏特化的用法(因为.NET泛型是运行时机制,考虑到.NET极强的meta data,个人觉得确实也不必要),但是C++/CLI使用的时候仍然可以利用模板来进行特化/偏特化处理。比如上面代码中的managed_Type_Traits<T^>类型就是用来提取不带^符号的原始类型,这样就可以让模板自动产生出gcnew T(...)这样的代码了。Anyway,C++的模板就跟宏(Macro)一样,就看你怎么运用其产生需要的代码了。
记得n年前学C++的时候看过不少讲模板特化,偏特化的资料,读STL、boost等Library源代码的时候也发现里面将模板元编程(TMP)的思想发挥的淋漓尽致。不过惭愧的是自己真正coding的时候还没直接用过,这次算是亲自试了一把,功能还是很强大的(当然请不要拿来与诸如Ruby这样的动态语言比,毕竟they are totally different)。
小结:玩TMP实际上就是与编译器斗,其乐无穷:)
- 将N层集合对象自动转化为对应的.NET泛型对象(C++)
- C#将DataTable转化为对应的对象
- jackson 将对象,集合转化为json
- json数据转化为对应的对象
- C语言将整形转化为对应的字符型
- 使用JAVA反射机制将简单JAVA been对象、数组转化为对应的Json串
- 【C# 工具类】将DataTable转化为 List集合/对象
- 将对象转化为DataTable
- 将对象转化为字符串
- 将java的pojo对象转化为flex vo对象
- 将JSON对象转化为实体对象
- 将mui对象转化为dom对象
- asp.net MVC 将 DataTable转化为客户端的JSon字符串及Ext JSon对象
- 优雅的将一个对象的集合转化成另一个对象的集合
- 将字符转化为对应的数字
- 将JSONArray转换为对应的对象数组
- List集合转化为json对象
- 将Object对象转化为String的几种方法
- Cone圆锥体节点
- 设计模式探索一
- 设计模式探索二
- 时寒冰:中国房价下跌序幕刚刚拉开
- 一位软件工程师的6年总结
- 将N层集合对象自动转化为对应的.NET泛型对象(C++)
- linux的内核调度
- 进入注册表的一些常用命令
- 另类加水印——根据明暗度分别加不同的水印
- 在线聊天系统雏形总结(续)
- 转帖(chinaunix 的creator):我的嵌入式学习之路(二) linux button 驱动
- Linux系统下信号量的用法
- Ubuntu 更新源
- linux-2.6.13下madplay在S3C2440上移植的全过程详解