Note that there are some explanatory texts on larger screens.

plurals
  1. POC++ implicit template instantiation
    primarykey
    data
    text
    <p>I currently have a class hierarchy like</p> <pre><code>MatrixBase -&gt; DenseMatrix -&gt; (other types of matrices) -&gt; MatrixView -&gt; TransposeView -&gt; DiagonalView -&gt; (other specialized views of matrices) </code></pre> <p><code>MatrixBase</code> is an abstract class which forces implementers to define operator()(int,int) and such things; it represents 2 dimensional arrays of numbers. <code>MatrixView</code> represents a (possibly mutable) way of looking at a matrix, like transposing it or taking a submatrix. The point of <code>MatrixView</code> is to be able to say something like</p> <pre><code>Scale(Diagonal(A), 2.0) </code></pre> <p>where <code>Diagonal</code> returns a <code>DiagonalView</code> object which is a kind of lightweight adapter.</p> <p>Now here's the question(s). I will use a very simple matrix operation as an example. I want to define a function like</p> <pre><code>template &lt;class T&gt; void Scale(MatrixBase&lt;T&gt; &amp;A, const T &amp;scale_factor); </code></pre> <p>which does the obvious thing the name suggests. I want to be able to pass in either an honest-to-goodness non-view matrix, or an instance of a subclass of <code>MatrixView</code>. The prototype as written above does not work for statements such as</p> <pre><code>Scale(Diagonal(A), 2.0); </code></pre> <p>because the <code>DiagonalView</code> object returned by <code>Diagonal</code> is a temporary, and <code>Scale</code> takes a non-const reference, which cannot accept a temporary. Is there any way to make this work? I tried to use SFINAE, but I don't understand it all that well, and I'm not sure if that would solve the problem. It is important to me that these templated functions can be called without providing an explicit template argument list (I want implicit instantiation). Ideally the statement above could work as written.</p> <hr> <p><strong>Edit: (followup question)</strong></p> <p>As sbi responded below about rvalue references and temporaries, Is there a way to define two versions of Scale, one which takes a non-const rvalue reference for non-views, and one which takes a pass-by-value view? The problem is to differentiate between these two at compile time in a way such that implicit instantiation will work.</p> <hr> <p><strong>Update</strong></p> <p>I've changed the class hierarchy to</p> <pre><code>ReadableMatrix WritableMatrix : public ReadableMatrix WritableMatrixView DenseMatrix : public WritableMatrix DiagonalView : public WritableMatrixView </code></pre> <p>The reason <code>WritableMatrixView</code> is distinct from <code>WritableMatrix</code> is that the view must be passed around by const reference, while the matrices themselves must be passed around by non-const ref, so the accessor member functions have different const-ness. Now functions like Scale can be defined as</p> <pre><code>template &lt;class T&gt; void Scale(const WritableMatrixView&lt;T&gt; &amp;A, const T &amp;scale_factor); template &lt;class T&gt; void Scale(WritableMatrix&lt;T&gt; &amp;A, const T &amp;scale_factor){ Scale(WritableMatrixViewAdapter&lt;T&gt;(A), scale_factor); } </code></pre> <p>Note that there are two versions, one for a const view, and a non-const version for actual matrices. This means for functions like <code>Mult(A, B, C)</code>, I will need 8 overloads, but at least it works. What doesn't work, however is using these functions within other functions. You see, each <code>View</code>-like class contains a member <code>View</code> of what it's looking at; for example in the expression <code>Diagonal(SubMatrix(A))</code>, the <code>Diagonal</code> function returns an object of type <code>DiagonalView&lt;SubMatrixView&lt;T&gt; &gt;</code>, which needs to know the fully derived type of <code>A</code>. Now, suppose within <code>Scale</code> I call some other function like it, which takes either a base view or matrix reference. That would fail because the construction of the needed <code>View</code>'s require the derived type of the argument of Scale; information it does not have. Still working on find a solution to this.</p> <hr> <p><strong>Update</strong></p> <p>I have used what is effectively a home-grown version of Boost's enable_if to select between two different versions of a function like <code>Scale</code>. It boils down to labeling all my matrix and view classes with extra typedef tags indicating if they are readable and writable and view or non-view. In the end, I still need 2^N overloads, but now N is only the number of non-const arguments. For the final result, see the <a href="http://github.com/victorliu/Templated-Numerics/tree/master/LinearAlgebra/" rel="nofollow noreferrer">here</a> (it's unlikely to get seriously revamped again).</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