Note that there are some explanatory texts on larger screens.

plurals
  1. POWhat is this pattern's name?
    primarykey
    data
    text
    <p>I have written a few template classes as part of a larger template class. One allows me to include or exclude member variables from a class. Another allows me to produce either the passed template class parameter or a placeholder that NOPs instead.</p> <p>These allow classes to use their own template parameters to include or exclude data members through a single very generic class definition, and the operations provide an interface that prevents type mismatch issues.</p> <p>This code sample shows my implementation in use as I assume it will be easier to recognise in action (the classes relating to the pattern have been called "ghost").</p> <pre><code>typedef int field1type, field2type, field3type; template &lt;bool field1exists, bool field2exists, bool field3exists&gt; struct GhostShowcase { typename Ghost&lt;int, field1exists&gt;::type intField; typename Ghost&lt;float, field2exists&gt;::type floatField; typename Ghost&lt;char, field3exists&gt;::type charField; }; GhostShowcase&lt;true,false,true&gt; foo; // has int and char fields // but an unusable float field GhostShowcase&lt;true,true,true&gt; bar; // has all fields usable </code></pre> <p>The samples below show how to use operators with the types derived from ghost classes. The testing function <code>printAll()</code> uses <code>ghostStaticOperator()</code> to call static functions in a class derived from <code>GhostStaticOperation</code>. This class is either the class that was passed as a template parameter to <code>GhostStaticOperation</code> or an automatically generated class which has a static function with the same signature but does nothing. The class chosen is based on the boolean template parameter <code>exists</code>. in <code>main()</code> two calls are made; the first passes the template parameter true and the second passes false. </p> <p>These samples show compilable source (in g++ 4.5.2, with -std=c++0x set). This file can be named anything.</p> <pre><code>#include "ghost.h" #include &lt;iostream&gt; #include &lt;functional&gt; using namespace Aryana; using namespace std; struct PrintingOperator : public std::unary_function&lt;int, void&gt; { static inline void operation(int toPrint) {cout &lt;&lt; toPrint;} }; struct IncrementOperator : public std::unary_function&lt;int&amp;, void&gt; { static inline void operation(int&amp; toIncrement) {++toIncrement;} }; template &lt;bool exists&gt; void printAll() { typedef GhostStaticOperator&lt;PrintingOperator, exists&gt; printClass; typedef GhostStaticOperator&lt;IncrementOperator, exists&gt; incrClass; typename Ghost&lt;int, exists&gt;::type ghostObject; cout &lt;&lt; "using ghost printer: "; ghostStaticOperation&lt;printClass&gt;(ghostObject); cout &lt;&lt; "\nusing ghost incrementor...\n"; ghostStaticOperation&lt;incrClass&gt;(ghostObject); cout &lt;&lt; "using ghost printer: "; ghostStaticOperation&lt;printClass&gt;(ghostObject); cout &lt;&lt; "\nfinished\n"; } int main(int, char**) { cout &lt;&lt; "ghost operation with exists=true:\n"; printAll&lt;true&gt;(); cout &lt;&lt; "ghost operation with exists=false:\n"; printAll&lt;false&gt;(); } </code></pre> <p>This sample should be named "ghost.h" and put in the same directory as the previous file.</p> <pre><code>typedef char ghost_null_argument[0]; typedef void ghost_null_return; template &lt;class S, bool exists&gt; class Ghost; template &lt;class S, bool exists&gt; class GhostOperator; template &lt;class S, bool exists&gt; class GhostStaticOperator; template &lt;class S&gt; class Ghost&lt;S, false&gt; { Ghost(); // private constructor to prevent instantiation public: typedef ghost_null_argument type; typedef S original_type; }; template &lt;class S&gt; class Ghost&lt;S, true&gt; { Ghost(); // private constructor to prevent instantiation public: typedef S type; typedef S original_type; }; template &lt;class S, bool exists&gt; class GhostOperator; template &lt;class S&gt; class GhostStaticOperator&lt;S, false&gt; { GhostStaticOperator(); // private constructor to prevent instantiation public: typedef ghost_null_return result_type; typedef ghost_null_argument argument_type; struct operator_type { inline static result_type operation(argument_type){}; }; }; template &lt;class S&gt; class GhostStaticOperator&lt;S, true&gt; { GhostStaticOperator(); // private constructor to prevent instantiation public: typedef S operator_type; typedef typename operator_type::result_type result_type; typedef typename operator_type::argument_type argument_type; }; // must define argument_type and result_type in the operator class // result_type will be ghost_null_argument if the class is ghosting template &lt;class S&gt; inline typename S::result_type ghostStaticOperation(typename S::argument_type argument) { return S::operator_type::operation(argument); } </code></pre>
    singulars
    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.
 

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