Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You are asking about dynamic functions, but your main problem is not there, but rather here:</p> <blockquote> <p>The return values of some of the functions being exposed through this interface are determined by the input parameter sKeyName.</p> </blockquote> <p>C++ is a statically typed language, and that means that you cannot have a return type for a function that is dependent on the value of the arguments. Ignoring for the time being inheritance, the code that you presented requires the user to determine the type of the array that is being returned <em>independently</em> of the arguments passed:</p> <pre><code>struct SimpleDataAccess { template &lt;typename T&gt; array2d&lt;T&gt;* get_data( std::string const &amp; which ) { return new array2d&lt;T&gt;(); } }; int main() { SimpleDataAccess accessor; array2d&lt;int&gt; = accessor.get&lt;int&gt;( "int" ); // &lt;int&gt; at the place of call fixes // the return type, not "int" ! } </code></pre> <p>Now, if you are willing to live with that (i.e. the caller will know and set the return type) there are different ways of providing workarounds for your particular problem of the language not allowing templated virtual functions. The first thing that comes to mind is nice in that it also follows the NVI idiom (and shows its importance): Provide a non-virtual public templated accessor to the data, and implement it in terms of a fixed return type virtual function.</p> <pre><code>class DataAccessor { virtual Type get_data_impl( std::string const &amp; ) = 0; public: template &lt;typename T&gt; array2d&lt;T&gt;* get_data( std::string const &amp; which ) { Type tmp = get_data_impl( which ); return convert( tmp ); } }; </code></pre> <p>Assuming that we can resolve what <code>Type</code> and <code>convert</code> are, we have a solution. This is a good example of the NVI idiom: the interface offered by users (public, non virtual) differs from the interface required to extensions (private, virtual). The two contracts differ, your users require you to provide a pointer to specific concrete <code>array2d</code> instantiation, but the language does not allow you to require that same contract from your extensions, but that is not a problem because they are <em>different</em> interfaces.</p> <p>Now back to <code>Type</code> and <code>convert</code>. These two are related, and there are different approaches that you can follow. The simplest to implement would be having an <code>array2d_base</code> class from which all <code>array2d&lt;T&gt;</code> derive (by providing a virtual destructor you enable RTTI):</p> <pre><code>struct array2d_base { virtual ~array2d_base() {} }; template &lt;typename T&gt; class array2d : public array2d_base { // implementation }; // Type == array2d_base* // convert == dynamic_cast&lt; array2d&lt;T&gt;* &gt; template &lt;typename T&gt; array2d&lt;T&gt;* DataAccessor::get_data( std::string const &amp; s ) { return dynamic_cast&lt; array2d&lt;T&gt;* &gt;( get_data_impl( s ) ); } </code></pre> <p>If you cannot extend or modify the <code>array2d</code> class, then you can achieve a similar result by means of type erasure. This will have the advantage of not requiring RTTI in <code>array2d</code> but only in the type erasing support. The simplest such implementation would be using <code>boost::any</code> in the inner interface:</p> <pre><code>// Type == boost::any // convert == boost::any_cast&lt; array2d&lt;T&gt;* &gt; template &lt;typename T&gt; array2d&lt;T&gt;* DataAccessor::get_data( std::string const &amp; s ) { boost::any tmp = get_data_impl(s); return boost::any_cast&lt; array2d&lt;T&gt;* &gt;( tmp ); } </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.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      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