<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>David's Blog : C++ Stuff</title><link>http://blogs.msdn.com/dowens/archive/tags/C_2B002B00_+Stuff/default.aspx</link><description>Tags: C++ Stuff</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Learning to call methods (C++ Reflection, part 2)</title><link>http://blogs.msdn.com/dowens/archive/2006/01/25/517736.aspx</link><pubDate>Thu, 26 Jan 2006 07:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:517736</guid><dc:creator>dowens</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/dowens/comments/517736.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dowens/commentrss.aspx?PostID=517736</wfw:commentRss><description>&lt;P&gt;Ok, last time we got the basics of the system in place. Tonight we'll fix up some of the stuff that we had before (in case you were wondering, I'm figuring this out at the same time as you guys), then get the invocation of some functions.&lt;/P&gt;
&lt;P&gt;First, our &lt;FONT face="Courier New"&gt;RuntimeInfo&lt;/FONT&gt; struct from last time is a little lacking and should be implementing a little better.&lt;/P&gt;&lt;!-- csharpformat manoli.net http: by formatted code --&gt;
&lt;DIV class=csharpcode&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   1:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; MapComparer&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   2:  &lt;/SPAN&gt;{&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   3:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt;:&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   4:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;bool&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;operator&lt;/SPAN&gt;()( &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;char&lt;/SPAN&gt;* s1, &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;char&lt;/SPAN&gt;* s2 ) &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   5:  &lt;/SPAN&gt;    {&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   6:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; strcmp(s1, s2) &amp;lt; 0;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   7:  &lt;/SPAN&gt;    }&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   8:  &lt;/SPAN&gt;};&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   9:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  10:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&lt;SPAN class=kwrd&gt;template&lt;/SPAN&gt;&lt;/SPAN&gt;&amp;lt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; T &amp;gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  11:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; RuntimeInfo&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  12:  &lt;/SPAN&gt;{&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  13:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt;:&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  14:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;static&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;SPAN class=kwrd&gt;unsigned&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; CLASS_NAME_LENGTH = 50;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  15:  &lt;/SPAN&gt;    &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  16:  &lt;/SPAN&gt;    RuntimeInfo( &lt;SPAN class=kwrd&gt;&lt;SPAN class=kwrd&gt;unsigned&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; classId, &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;char&lt;/SPAN&gt;* name );&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  17:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  18:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;&lt;SPAN class=kwrd&gt;unsigned&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; GetClassId() &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt;;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  19:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;char&lt;/SPAN&gt;* GetClassName() &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt;;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  20:  &lt;/SPAN&gt;    &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  21:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; RegisterMethod( Method&amp;lt; T &amp;gt;* method );&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  22:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  23:  &lt;/SPAN&gt;    Method&amp;lt; T &amp;gt;* GetMethod( &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;char&lt;/SPAN&gt;* name );&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  24:  &lt;/SPAN&gt;    std::map&amp;lt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;char&lt;/SPAN&gt;*, Method&amp;lt; T &amp;gt;*, MapComparer &amp;gt;* GetMethods();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  25:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  26:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;private&lt;/SPAN&gt;:    &lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  27:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;&lt;SPAN class=kwrd&gt;unsigned&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; _classId;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  28:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;char&lt;/SPAN&gt;         _className[ CLASS_NAME_LENGTH ];&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  29:  &lt;/SPAN&gt;    std::map&amp;lt; &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;char&lt;/SPAN&gt;*, Method&amp;lt; T &amp;gt;*, MapComparer &amp;gt; _methods;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  30:  &lt;/SPAN&gt;};&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;The first changes to note is the change from a struct to a class. This is technically only a semantic change in C++, but we'll be adding functionality via functions so it's better to call it a class. Next, I moved the class ID and name to private member data, which it probably should have been in the first place. You should also notice that the class is now a templated class. The templace type will tell us the type for member methods will be called. The last important thing is the addition of the RegisterMethod function. This allows us to register any member function with the class so that we can later invoke it.&lt;/P&gt;
&lt;P&gt;Alright, now that we've updated the &lt;FONT face="Courier New"&gt;RuntimeInfo&lt;/FONT&gt; class to support our &lt;FONT face="Courier New"&gt;Method&lt;/FONT&gt;s, let's go ahead and define those. =)&lt;/P&gt;&lt;!-- csharpformat manoli.net http: by formatted code --&gt;
&lt;DIV class=csharpcode&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   1:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;template&lt;/SPAN&gt;&amp;lt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; OwnerType &amp;gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   2:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; Method&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   3:  &lt;/SPAN&gt;{&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   4:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt;:&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   5:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;typedef&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; (OwnerType::*m0)();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   6:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   7:  &lt;/SPAN&gt;    Method( &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;char&lt;/SPAN&gt;* name, m0 method );&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   8:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;virtual&lt;/SPAN&gt; ~Method();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   9:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  10:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;char&lt;/SPAN&gt;* GetName() &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt;;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  11:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  12:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; Invoke( OwnerType&amp;amp; obj );&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  13:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  14:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;protected&lt;/SPAN&gt;:&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  15:  &lt;/SPAN&gt;    Method( &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;char&lt;/SPAN&gt;* name );&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  16:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  17:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;private&lt;/SPAN&gt;:&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  18:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;char&lt;/SPAN&gt;* _methodName;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  19:  &lt;/SPAN&gt;    m0 _method;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  20:  &lt;/SPAN&gt;};&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;Our &lt;FONT face="Courier New"&gt;Method&lt;/FONT&gt; class is pretty straight forward; it will be used to define functions that have no return type, and for now, take no parameters. First, this class is templated to define the type for the function that is being passed in. For instance, if I have a class &lt;FONT face="Courier New"&gt;MyInt&lt;/FONT&gt; and have exposed Double(), the type would be &lt;FONT face="Courier New"&gt;MyInt&lt;/FONT&gt;. Next thing to note is the typedef for the function signature; this is a function that returns void and takes no parameters. The next interesting piece is the Invoke() function; this is where all of the action will actually be done.&lt;/P&gt;
&lt;P&gt;You might be wondering why I've created a protected Method constructor... that's a good question. The reason is that when I start extending this class, I want to be able to take advantage of the base functionality for storing the name.&lt;/P&gt;
&lt;P&gt;Alright, so this gives us the ability to call functions that don't return anything, let's extend it so that we can call a function and have it return something interesting.&lt;/P&gt;
&lt;DIV class=csharpcode&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   1:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;template&lt;/SPAN&gt;&amp;lt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; OwnerType, &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; ReturnType &amp;gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   2:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; Function : &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; Method&amp;lt; OwnerType &amp;gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   3:  &lt;/SPAN&gt;{&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   4:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt;:&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   5:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;typedef&lt;/SPAN&gt; ReturnType (OwnerType::*f0)();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   6:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   7:  &lt;/SPAN&gt;    Function( &lt;SPAN class=kwrd&gt;const&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;char&lt;/SPAN&gt;* name, f0 function );&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   8:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;virtual&lt;/SPAN&gt; ~Function();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   9:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  10:  &lt;/SPAN&gt;    ReturnType Invoke( OwnerType&amp;amp; obj );&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  11:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  12:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;private&lt;/SPAN&gt;:&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  13:  &lt;/SPAN&gt;    f0 _method;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  14:  &lt;/SPAN&gt;};&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;The major difference between this class and the &lt;FONT face="Courier New"&gt;Method&lt;/FONT&gt; class is that this class takes two template arguments: the type for the member function and the return type for the function. Also notice the overloading of the Invoke() function so that it returns the proper type.&lt;/P&gt;
&lt;P&gt;And that's all there is to it. I'll post a little sample application that shows it in use.&lt;/P&gt;&lt;!-- csharpformat manoli.net http: by formatted code --&gt;
&lt;DIV class=csharpcode&gt;
&lt;PRE&gt;&lt;SPAN class=lnum&gt;   1:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;PRE&gt;&lt;SPAN class=lnum&gt;   2:  &lt;/SPAN&gt;_tmain( &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; argc, _TCHAR* argv[] )&lt;/PRE&gt;
&lt;PRE&gt;&lt;SPAN class=lnum&gt;   3:  &lt;/SPAN&gt;{&lt;/PRE&gt;
&lt;PRE&gt;&lt;SPAN class=lnum&gt;   4:  &lt;/SPAN&gt;    Object o;&lt;/PRE&gt;
&lt;PRE&gt;&lt;SPAN class=lnum&gt;   5:  &lt;/SPAN&gt;    MyInt i;&lt;/PRE&gt;
&lt;PRE&gt;&lt;SPAN class=lnum&gt;   6:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;
&lt;PRE&gt;&lt;SPAN class=lnum&gt;   7:  &lt;/SPAN&gt;    i.SetValue( 30 );&lt;/PRE&gt;
&lt;PRE&gt;&lt;SPAN class=lnum&gt;   8:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;
&lt;PRE&gt;&lt;SPAN class=lnum&gt;   9:  &lt;/SPAN&gt;    Method&amp;lt; MyInt &amp;gt;* imi = i.GetRuntimeInfo()-&amp;gt;GetMethod( &lt;SPAN class=str&gt;"Double"&lt;/SPAN&gt; );&lt;/PRE&gt;
&lt;PRE&gt;&lt;SPAN class=lnum&gt;  10:  &lt;/SPAN&gt;    Function&amp;lt; MyInt, &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; &amp;gt;* imi2 =&lt;/PRE&gt;
&lt;PRE&gt;&lt;SPAN class=lnum&gt;  11:  &lt;/SPAN&gt;        &lt;SPAN class=kwrd&gt;static_cast&lt;/SPAN&gt;&amp;lt; Function&amp;lt; MyInt, &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; &amp;gt;* &amp;gt;( i.GetRuntimeInfo()-&amp;gt;GetMethod( &lt;SPAN class=str&gt;"GetValue"&lt;/SPAN&gt; ) );&lt;/PRE&gt;
&lt;PRE&gt;&lt;SPAN class=lnum&gt;  12:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  13:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"-- OBJECT --"&lt;/SPAN&gt; &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  14:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"\tClass ID: "&lt;/SPAN&gt; &amp;lt;&amp;lt; o.GetRuntimeInfo()-&amp;gt;GetClassId() &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  15:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"\tClass Name: "&lt;/SPAN&gt; &amp;lt;&amp;lt; o.GetRuntimeInfo()-&amp;gt;GetClassName() &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  16:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  17:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  18:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"-- MYINT --"&lt;/SPAN&gt; &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  19:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"\tClass ID: "&lt;/SPAN&gt; &amp;lt;&amp;lt; i.GetRuntimeInfo()-&amp;gt;GetClassId() &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  20:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"\tClass Name: "&lt;/SPAN&gt; &amp;lt;&amp;lt; i.GetRuntimeInfo()-&amp;gt;GetClassName() &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  21:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"\tOriginal Value: "&lt;/SPAN&gt; &amp;lt;&amp;lt; i.GetValue() &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  22:  &lt;/SPAN&gt;    imi-&amp;gt;Invoke( i );&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  23:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"\tDouble Value: "&lt;/SPAN&gt; &amp;lt;&amp;lt; i.GetValue() &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  24:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"\tGetValue: "&lt;/SPAN&gt; &amp;lt;&amp;lt; imi2-&amp;gt;Invoke( i ) &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  25:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  26:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  27:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"Press enter to exit."&lt;/SPAN&gt; &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  28:  &lt;/SPAN&gt;    cin.get();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  29:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  30:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; 0;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  31:  &lt;/SPAN&gt;}&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;So there we have it. We've built a reflection system in C++. Is it the most robust and feature rich, no, most definately not. For instance, there is not way to pass in arguments to either the &lt;FONT face="Courier New"&gt;Method&lt;/FONT&gt; or &lt;FONT face="Courier New"&gt;Function&lt;/FONT&gt; class, there is no way to call the constructor, although, arguably that is just registering the constructor with by using the &lt;FONT face="Courier New"&gt;Function&lt;/FONT&gt; class. But overall, I think I've pretty much met the goal that I set out to achieve.&lt;/P&gt;
&lt;P&gt;If you have any questions or comments, I'd be happy to answer them, but I think I'm relatively happy with the reflection system I have in C++... for now atleast. =)&lt;/P&gt;
&lt;P&gt;Source Code: &lt;A href="http://www.ihhome.com/users/owensd/files/Reflection.zip"&gt;Reflection.zip&lt;/A&gt;&lt;/P&gt;
&lt;DIV&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=517736" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dowens/archive/tags/C_2B002B00_+Stuff/default.aspx">C++ Stuff</category></item><item><title>Thinking about the problem (C++ Reflection, part 1)</title><link>http://blogs.msdn.com/dowens/archive/2006/01/21/515861.aspx</link><pubDate>Sun, 22 Jan 2006 03:19:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:515861</guid><dc:creator>dowens</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/dowens/comments/515861.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dowens/commentrss.aspx?PostID=515861</wfw:commentRss><description>&lt;P&gt;&lt;STRONG&gt;&lt;FONT size=4&gt;Setting Goals&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;So you want to build a reflection system in C++? Well, I assume so since you're reading this. =) Ok, enough jokes...&lt;/P&gt;
&lt;P&gt;There are a few ways to go about building a reflection system in C++ and there are different levels that we can accomplish. For instance, to create a reflection based system that works without any modification to standard C++ types and classes would be very challenging, to say the least. In order to help us with this problem, we'll start off with a set of goals so that we know what we want to aim for.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Maintainable&lt;/STRONG&gt; - It would be nice if (and when) we need to make modifications or bug fixes the code base is clean and logical. 
&lt;LI&gt;&lt;STRONG&gt;Robust&lt;/STRONG&gt; - I don't like when things only work when sprinkling some magic pixie dust, so let's make this thing as robust as possible. This means we'll be using templates rather than MACROs to do our magic. 
&lt;LI&gt;&lt;STRONG&gt;Effecient&lt;/STRONG&gt; - The idea isn't to create a reflection system takes five minutes to perform something, we want a small and fast system. 
&lt;LI&gt;&lt;STRONG&gt;Flexible&lt;/STRONG&gt; - Let's shoot for making an extensible system so that we can add to it later without too many problems.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;I think that those goals are good enough to get started.&lt;/P&gt;
&lt;P&gt;&lt;FONT size=4&gt;&lt;STRONG&gt;Where to Start&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;In order to being programming this thing we need to understand what type of information we want. For now the only things that we will concern ourselves with are unique ID for the class and the name of the class; we'll add to it later to actually make it do some cool stuff.&lt;/P&gt;
&lt;P&gt;To start off we'll need the following classes to provide us with some basic run-time information: &lt;FONT face="Courier New"&gt;RuntimeInfo &lt;/FONT&gt;and &lt;FONT face="Courier New"&gt;RuntimeClass&lt;/FONT&gt;.&lt;/P&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;struct&lt;/span&gt; RuntimeInfo&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    RuntimeInfo( &lt;span class="kwrd"&gt;unsigned&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; classId, &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;char&lt;/span&gt;* name );&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;unsigned&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; CLASS_NAME_LENGTH = 32;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    &lt;span class="kwrd"&gt;unsigned&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; ClassId;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    &lt;span class="kwrd"&gt;char&lt;/span&gt;         ClassName[ CLASS_NAME_LENGTH ];&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;};&lt;/pre&gt;
&lt;/div&gt;
&lt;P&gt;This class will define all of the cool details for our class; currently we only need to know the ID for the and the name for the class. The ID could be used to create a new type of class or to compare is two classes are the same.&lt;/P&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;template&lt;/span&gt;&amp;lt; &lt;span class="kwrd"&gt;class&lt;/span&gt; T, &lt;span class="kwrd"&gt;class&lt;/span&gt; BaseClass, &lt;span class="kwrd"&gt;unsigned&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; ClassId &amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; RuntimeClass : &lt;span class="kwrd"&gt;public&lt;/span&gt; BaseClass&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt;:&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; inline RuntimeInfo* GetRuntimeInfo() { &lt;span class="kwrd"&gt;return&lt;/span&gt; &amp;amp;_info; }&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt;:&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; RuntimeInfo _info;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;};&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;&lt;span class="kwrd"&gt;template&lt;/span&gt;&amp;lt; &lt;span class="kwrd"&gt;class&lt;/span&gt; T, &lt;span class="kwrd"&gt;class&lt;/span&gt; BaseClass, &lt;span class="kwrd"&gt;unsigned&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; ClassId &amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;RuntimeInfo&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;RuntimeClass&amp;lt; T, BaseClass, ClassId &amp;gt;::_info( ClassId, typeid( T ).name() );&lt;/pre&gt;
&lt;/div&gt;
&lt;P&gt;I hope you're up to speed with your templates =). This class is a tricky way of injecting information that is shared by each type of class we'll be using in our reflection system. All this class currently has is the runtime information that is created based on the templated information.&lt;/P&gt;
&lt;P&gt;The next step is to create the base class we'll be using for all of the objects in our system; it's appropriately named &lt;FONT face="Courier New"&gt;Object&lt;/FONT&gt;.&lt;/P&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;DIV class=csharpcode&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   1:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; NullObject{};&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   2:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; Object : &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; RuntimeClass&amp;lt; Object, NullObject, 0x0A &amp;gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   3:  &lt;/SPAN&gt;{&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   4:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt;:&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   5:  &lt;/SPAN&gt;    Object();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   6:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;virtual&lt;/SPAN&gt; ~Object();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   7:  &lt;/SPAN&gt;};&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;One of the first things to notice is that it implements our &lt;FONT face="Courier New"&gt;RuntimeClass&lt;/FONT&gt; and passes in the type that it is, the type it derives from, and the ID to use for the class. As you can see, there is another class &lt;FONT face="Courier New"&gt;NullObject&lt;/FONT&gt; here; this is used so that are template parameters will be satisfied.&lt;/P&gt;
&lt;P&gt;That's it! I've given a very brief breakdown of what it takes to get started building a reflection system. Next time we'll learn how set it up so we can create new instances and set some properties on our classes. I'll leave you with a little sample app that shows it working.&lt;/P&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;DIV class=csharpcode&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   1:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; MyClass : &lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; RuntimeClass&amp;lt; MyClass, Object, 0xF0 &amp;gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   2:  &lt;/SPAN&gt;{&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   3:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt;:&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   4:  &lt;/SPAN&gt;    MyClass();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   5:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;virtual&lt;/SPAN&gt; ~MyClass();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   6:  &lt;/SPAN&gt;};&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   7:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   8:  &lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;   9:  &lt;/SPAN&gt;_tmain( &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; argc, _TCHAR* argv[] )&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  10:  &lt;/SPAN&gt;{&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  11:  &lt;/SPAN&gt;    Object o;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  12:  &lt;/SPAN&gt;    MyClass c;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  13:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  14:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"-- OBJECT --"&lt;/SPAN&gt; &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  15:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"\tClass ID: "&lt;/SPAN&gt; &amp;lt;&amp;lt; o.GetRuntimeInfo()-&amp;gt;ClassId &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  16:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"\tClass Name: "&lt;/SPAN&gt; &amp;lt;&amp;lt; o.GetRuntimeInfo()-&amp;gt;ClassName &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  17:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  18:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  19:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"-- MYCLASS --"&lt;/SPAN&gt; &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  20:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"\tClass ID: "&lt;/SPAN&gt; &amp;lt;&amp;lt; c.GetRuntimeInfo()-&amp;gt;ClassId &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  21:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"\tClass Name: "&lt;/SPAN&gt; &amp;lt;&amp;lt; c.GetRuntimeInfo()-&amp;gt;ClassName &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  22:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  23:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  24:  &lt;/SPAN&gt;    cout &amp;lt;&amp;lt; &lt;SPAN class=str&gt;"Press enter to exit."&lt;/SPAN&gt; &amp;lt;&amp;lt; endl;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  25:  &lt;/SPAN&gt;    cin.get();&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  26:  &lt;/SPAN&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  27:  &lt;/SPAN&gt;    &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; 0;&lt;/PRE&gt;&lt;PRE&gt;&lt;SPAN class=lnum&gt;  28:  &lt;/SPAN&gt;}&lt;/PRE&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=515861" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dowens/archive/tags/C_2B002B00_+Stuff/default.aspx">C++ Stuff</category></item></channel></rss>