Note that there are some explanatory texts on larger screens.

plurals
  1. POMimicing C# 'new' (hiding a virtual method) in a C++ code generator
    primarykey
    data
    text
    <p>I'm developing a system which takes a set of compiled .NET assemblies and emits C++ code which can then be compiled to any platform having a C++ compiler. Of course, this involves some extensive trickery due to various things .NET does that C++ doesn't.</p> <p>One such situation is the ability to hide virtual methods, such as the following in C#:</p> <pre><code>class A { virtual void MyMethod() { ... } } class B : A { override void MyMethod() { ... } } class C : B { new virtual void MyMethod() { ... } } class D : C { override void MyMethod() { ... } } </code></pre> <p>I came up with a solution to this that seemed clever and did work, as in the following example:</p> <pre><code>namespace impdetails { template&lt;class by_type&gt; struct redef {}; } struct A { virtual void MyMethod( void ); }; struct B : A { virtual void MyMethod( void ); }; struct C : B { virtual void MyMethod( impdetails::redef&lt;C&gt; ); }; struct D : C { virtual void MyMethod( impdetails::redef&lt;D&gt; ); }; </code></pre> <p>This does of course require that all the call sites for <code>C::MyMethod</code> and <code>D::MyMethod</code> construct and pass the dummy object, as in this example:</p> <pre><code>C *c_d = &amp;d; c_d-&gt;MyMethod( impdetails::redef&lt;C&gt;() ); </code></pre> <p>I'm not worried about this extra <em>source code</em> overhead; the output of this system is mainly not intended for human consumption.</p> <p>Unfortunately, it turns out this actually causes <em>runtime</em> overhead. Intuitively, one would expect that because <code>impdetails::redef&lt;&gt;</code> is empty, it would take no space and passing it would involve no code.</p> <p>However, the C++ standard, for reasons I understand but don't totally agree with, mandates that objects cannot have zero size. This leaves us with a situation where the compiler actually emits code to create and pass the object.</p> <p>In fact, at least on VC2008, I found that it even went to the trouble of zeroing the dummy byte, even in release builds! I'm not sure why <em>that</em> was necessary, but it makes me even more not want to do it this way.</p> <p>If all else fails I could always change the actual name of the function, such as perhaps having <code>MyMethod</code>, <code>MyMethod$1</code>, and <code>MyMethod$2</code>. However, this causes more problems. For instance, <code>$</code> is actually not legal in C++ identifiers (although compilers I've tested will allow it.) A totally acceptable identifier in the output program could also be an identifier in the input program, which suggests a more complex approach would be needed, making this a less attractive option.</p> <p>It also so turns out that there are other situations in this project where it would be nice to be able to modify method signatures using arbitrary type arguments similar to how I'm passing a type to <code>impdetails::redef&lt;&gt;</code>.</p> <p>Is there any other clever way to get around this, or am I stuck between adding overhead at every call site or mangling names?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload