Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to achieve dynamic polymorphism (run-time call dispatch) on unrelated types?
    primarykey
    data
    text
    <p><strong>GOAL:</strong></p> <p>I would like to achieve <strong>type-safe dynamic polymorphism</strong> (i.e. run-time dispatch of a function call) <strong>on unrelated types</strong> - i.e. on types which <em>do not have a common base class</em>. It seems to me that this is achievable, or at least theoretically sound. I will try to define my problem more formally.</p> <p><strong>PROBLEM DEFINITION:</strong></p> <p>Given the following:</p> <ul> <li>two or more <strong>unrelated</strong> types <code>A1, ..., An</code>, each of which has a method called <code>f</code>, possibly with different signatures, but <strong>with the same return type</strong> <code>R</code>; and</li> <li>a <code>boost::variant&lt;A1*, ..., An*&gt;</code> object <code>v</code> (or whatever other type of variant) which can and <em>must</em> assume at any time one value of any of those types;</li> </ul> <p>My goal is to write instructions conceptually equivalent to <code>v.f(arg_1, ..., arg_m);</code> that would get <strong>dispatched at run-time</strong> to function <code>Ai::f</code> if the <em>actual type</em> of the value contained in <code>v</code> is <code>Ai</code>. If the call arguments are not compatible with the formal parameters of <strong>each</strong> function <code>Ai</code>, the compiler should raise an error. </p> <p>Of course I do not need to stick to the syntax <code>v.f(arg_1, ..., arg_m)</code>: for instance, something like <code>call(v, f, ...)</code> is also acceptable.</p> <p>I tried to achieve this in C++, but so far I have failed to come up with a <strong>good</strong> solution (I do have a bunch of bad ones). Below I clarify what I mean by "good solution".</p> <p><strong>CONSTRAINTS:</strong></p> <p>A <strong>good solution</strong> is anything that lets me mimic the <code>v.f(...)</code> idiom, e.g. <code>call_on_variant(v, f, ...);</code>, and <em>satisfies the following constraints</em>:</p> <ol> <li>does not require any sort of <strong>separate declaration</strong> for each function <code>f</code> that must be called this way (e.g. <code>ENABLE_CALL_ON_VARIANT(f)</code>) or for any list of unrelated types <code>A1, ..., An</code> that can be treated polymorphically (e.g. <code>ENABLE_VARIANT_CALL(A1, ..., An)</code>) somewhere else in the code, especially on global scope;</li> <li>does not require to <strong>explicitly name the types of the input arguments</strong> when doing the call (e.g. <code>call_on_variant&lt;int, double, string&gt;(v, f, ...)</code>). Naming the <em>return</em> type is OK, so for instance <code>call_on_variant&lt;void&gt;(v, f, ...)</code> is acceptable.</li> </ol> <p>Follows a demonstrative example that hopefully clarifies my wish and requirements.</p> <p><strong>EXAMPLE:</strong></p> <pre><code>struct A1 { void f(int, double, string) { cout &lt;&lt; "A"; } }; struct A2 { void f(int, double, string) { cout &lt;&lt; "B"; } }; struct A3 { void f(int, double, string) { cout &lt;&lt; "C"; } }; using V = boost::variant&lt;A1, A2, A3&gt;; // Do not want anything like the following here: // ENABLE_VARIANT_CALL(foo, &lt;whatever&gt;) int main() { A a; B b; C c; V v = &amp;a; call_on_variant(v, f, 42, 3.14, "hello"); // Do not want anything like the following here: // call_on_variant&lt;int, double, string&gt;(v, f, 42, 3.14, "hello"); V v = &amp;b; call_on_variant(v, f, 42, 3.14, "hello"); V v = &amp;c; call_on_variant(v, f, 42, 3.14, "hello"); } </code></pre> <p>The output of this program should be: <code>ABC</code>.</p> <p><strong>BEST (FAILED) ATTEMPT:</strong></p> <p>The closest I got to the desired solution is this macro:</p> <pre><code>#define call_on_variant(R, v, f, ...) \ [&amp;] () -&gt; R { \ struct caller : public boost::static_visitor&lt;void&gt; \ { \ template&lt;typename T&gt; \ R operator () (T* pObj) \ { \ pObj-&gt;f(__VA_ARGS__); \ } \ }; \ caller c; \ return v.apply_visitor(c); \ }(); </code></pre> <p>Which would work perfectly, <strong>if only template members were allowed in local classes</strong> (see <a href="https://stackoverflow.com/questions/4299314/member-template-in-local-class">this question</a>). Does anybody have an idea how to fix this, or suggest an alternative approach?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    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