Note that there are some explanatory texts on larger screens.

plurals
  1. POsimulate C++ function template instantiation with implicit conversion
    primarykey
    data
    text
    <p>I already asked <a href="https://stackoverflow.com/questions/1741840/c-implicit-template-instantiation">two</a> <a href="https://stackoverflow.com/questions/1746352/how-to-have-templated-function-overloads-accept-derived-classes-from-different-ba">questions</a> related to what I'm trying to do (one resolved, one of which I will close soon). I know that C++ template instantiation does not allow any implicit conversions (see for example <a href="https://stackoverflow.com/questions/867462/c-implicit-conversions/868398#868398">this comment</a>), but I would like to simulate it.</p> <p>Suppose I have the following skeleton code:</p> <pre><code>template &lt;class T&gt; struct Base_A{ virtual void interface_func() const = 0; }; template &lt;class T&gt; struct Derived_A : public Base_A&lt;T&gt;{ typedef T value_type; void interface_func() const{} }; template &lt;class T&gt; struct Base_B{ virtual void interface_func() = 0; // note: non-const }; template &lt;class T&gt; struct Derived_B : public Base_B&lt;T&gt;{ typedef T value_type; void interface_func(){} }; template &lt;class BType&gt; struct Adapter : public Base_A&lt;typename BType::value_type&gt;{ BType &amp;ref_B; Adapter(BType &amp;inst_B):ref_B(B_inst){} void interface_func() const{} // does stuff with ref_B to simulate an A }; template &lt;class Should_Always_Be_Base_A&gt; void f(const Should_Always_Be_Base_A &amp;arg){ // Only Base_A can be passed in by const ref // Passing in a Base_B by const ref would not work. } Derived_A&lt;int&gt; A; Derived_B&lt;int&gt; B; f(A); // passes in A by const ref f(B); // I want to pass in Adapter&lt;Derived_B&lt;int&gt; &gt;(B) </code></pre> <p>I want the template parameter for function <code>f</code> to always be a derived class of <code>Base_A</code> or an <code>Adapter</code>. The answer to restricting the type of <code>arg</code> <a href="https://stackoverflow.com/questions/1746352/how-to-have-templated-function-overloads-accept-derived-classes-from-different-ba">can be done</a>, but the implicit conversion to an Adapter cannot. Is there any way to do this? The net result is I want to be able to call <code>f</code> as <code>f(A)</code> or <code>f(B)</code>, and in both cases I need to know the actual derived type of A or B within <code>f</code> (<code>f</code> cannot just see a reference to the base class).</p> <p><strong>Aside:</strong></p> <p>Presently, I just have <code>f(A)</code> working, and <code>f(B)</code> actually calls an overload which performs the Adapter construction, but I have other functions which take N arguments, each of which can be A or B, so I would need 2^N overloads.</p> <p>For the curious, this is in application to the matrix library I'm working on. <code>Base_A</code> represents the base matrix type, and <code>Base_B</code> represents the base matrix-view type. For operations which will modify a matrix argument, I need to pass in the matrix by non-const reference or a modifiable matrix-view by const-ref. The adapter is just a trivial matrix-to-view adapter. So for example, I currently have a function like</p> <pre><code>Scale(const MatrixViewBase&lt;T&gt; &amp;Mview, const T &amp;scale_factor){ // does the actual work } Scale(MatrixBase&lt;T&gt; &amp;M, const T &amp;scale_factor){ Scale(Adapter&lt;MatrixBase&lt;T&gt; &gt;(M), scale_factor); } </code></pre> <p>It's tedious and error prone to make 2^N copies of all these functions just to create the needed overloads to handle both views and non-views. As is, this is not good enough since I want Scale to be able to know the full derived type of Mview, not just the base class, because I will potentially generate instances of types dependent on Mview.</p> <p><strong>Edit 1:</strong> Changed all B types to have non-const interface functions. This was the original intent, so apologies for any confusion.</p> <p><strong>Edit 2:</strong> Have this working code, still requires 2^N overloads, but I can live with it unless someone suggests how to deal with that.</p> <pre><code>#include &lt;iostream&gt; template &lt;class T&gt; struct ReadableMatrix{ typedef T value_type; }; template &lt;class T&gt; struct WritableMatrix{ typedef T value_type; }; template &lt;class T&gt; struct WritableMatrixView{ typedef T value_type; }; template &lt;class T&gt; struct Matrix : public WritableMatrix&lt;T&gt;{ typedef T value_type; typedef ReadableMatrix&lt;T&gt; readable_matrix; typedef WritableMatrix&lt;T&gt; writable_matrix; }; template &lt;class T&gt; struct MatrixView : public WritableMatrixView&lt;T&gt;{ typedef T value_type; typedef ReadableMatrix&lt;T&gt; readable_matrix; // not really used; needs an adapter before using typedef WritableMatrixView&lt;T&gt; writable_matrix; }; template &lt;class T, class R&gt; struct IsReadableMatrix{ }; template &lt;class T, class R&gt; struct IsReadableMatrix&lt;ReadableMatrix&lt;T&gt;, R&gt;{ typedef R type; }; template &lt;class T, class R&gt; struct IsWritableMatrix{ }; template &lt;class T, class R&gt; struct IsWritableMatrix&lt;WritableMatrix&lt;T&gt;, R&gt;{ typedef R type; }; template &lt;class T, class R&gt; struct IsWritableMatrixView{ }; template &lt;class T, class R&gt; struct IsWritableMatrixView&lt;WritableMatrixView&lt;T&gt;, R&gt;{ typedef R type; }; template &lt;class TA, class TB&gt; typename IsReadableMatrix&lt;typename TA::readable_matrix, typename IsWritableMatrixView&lt;typename TB::writable_matrix, void &gt;::type&gt;::type Copy(const TA &amp;A, const TB &amp;B){ std::cout &lt;&lt; "Here" &lt;&lt; std::endl; } template &lt;class TA, class TB&gt; typename IsReadableMatrix&lt;typename TA::readable_matrix, typename IsWritableMatrix&lt;typename TB::writable_matrix, void &gt;::type&gt;::type Copy(const TA &amp;A, TB &amp;B){ std::cout &lt;&lt; "Here2" &lt;&lt; std::endl; } int main(){ Matrix&lt;int&gt; M, M2; MatrixView&lt;int&gt; V, V2; Copy(M, M2); Copy(V, V2); Copy(M, V); Copy(V, M); } </code></pre>
    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