When someone encountered a problem yesterday, I came back at night and thought about a solution to type deduction using templates.
The problem itself needs to be clear, that is, you need to write an util function to automatically convert the template set objects in C ++.. Net (for example, convert vector <int> to list <int> ^. Because the type is not fixed, it is the best choice to use a template for conversion. The difficulty is that these collection classes can also be nested types, that is to say, the set is still installed in the Set (for example, converting the vector <int> to list <int> ^), and even the nested multi-layer set needs to be considered.
- // 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, role <internalnativetype >:: iscollection (), role <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 <int >=> 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 <int>, list <int> ^> (ivv );
- For each (list <int> ^ L in List)
- {
- For each (int I in L)
- Console: Write ("{0}", I );
- Console: writeline ();
- }
- //---------------------------------
- // Test vector <string >=> 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 <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;
- }
The code above will not be explained much. For more information about type traits, see this article. For more information about specialization and partial specialization, see Mr Hou Jie's STL source code analysis. In particular, though. net generic principle does not support the use of special and biased (because. net generic is the runtime mechanism, considering. net strong meta data, I personally think it is not necessary), but the C ++/CLI can still use templates for special/partial special processing. For example, the managed_type_traits <t ^> type in the above code is used to extract the original type without the ^ symbol, so that the template can automatically generate gcnew T (...) this is the code. The anyway and C ++ templates are the same as those of macro (macro), depending on how you use them to generate the required code.
I remember reading a lot of special and special templates when I learned C ++ N years ago. When I read the source code of libraries such as STL and boost, I also found that the template metadata programming (TMP) the idea is fully realized. But I am ashamed that I haven't used coding before. I tried it myself this time, the function is still very powerful (please do not compare it with dynamic languages such as Ruby, after all they are totally different ).
Conclusion: Playing TMP is actually a battle with the compiler. It's fun :)