Template documentation tweaks

Add subsections to the template documentation
Rewrite some of the template introduction
This commit is contained in:
William S Fulton 2017-08-08 19:40:39 +01:00
commit 97ae9d66bc
2 changed files with 146 additions and 90 deletions

View file

@ -246,6 +246,15 @@
<li><a href="SWIGPlus.html#SWIGPlus_nn28">Wrapping overloaded operators</a> <li><a href="SWIGPlus.html#SWIGPlus_nn28">Wrapping overloaded operators</a>
<li><a href="SWIGPlus.html#SWIGPlus_class_extension">Class extension</a> <li><a href="SWIGPlus.html#SWIGPlus_class_extension">Class extension</a>
<li><a href="SWIGPlus.html#SWIGPlus_nn30">Templates</a> <li><a href="SWIGPlus.html#SWIGPlus_nn30">Templates</a>
<ul>
<li><a href="SWIGPlus.html#SWIGPlus_template_directive">The %template directive</a>
<li><a href="SWIGPlus.html#SWIGPlus_template_functions">Function templates</a>
<li><a href="SWIGPlus.html#SWIGPlus_template_classes">Default template arguments</a>
<li><a href="SWIGPlus.html#SWIGPlus_template_class_inheritance">Template base classes</a>
<li><a href="SWIGPlus.html#SWIGPlus_template_specialization">Template specialization</a>
<li><a href="SWIGPlus.html#SWIGPlus_template_member">Member templates</a>
<li><a href="SWIGPlus.html#SWIGPlus_template_more">More on templates</a>
</ul>
<li><a href="SWIGPlus.html#SWIGPlus_namespaces">Namespaces</a> <li><a href="SWIGPlus.html#SWIGPlus_namespaces">Namespaces</a>
<ul> <ul>
<li><a href="SWIGPlus.html#SWIGPlus_nspace">The nspace feature for namespaces</a> <li><a href="SWIGPlus.html#SWIGPlus_nspace">The nspace feature for namespaces</a>

View file

@ -49,6 +49,15 @@
<li><a href="#SWIGPlus_nn28">Wrapping overloaded operators</a> <li><a href="#SWIGPlus_nn28">Wrapping overloaded operators</a>
<li><a href="#SWIGPlus_class_extension">Class extension</a> <li><a href="#SWIGPlus_class_extension">Class extension</a>
<li><a href="#SWIGPlus_nn30">Templates</a> <li><a href="#SWIGPlus_nn30">Templates</a>
<ul>
<li><a href="#SWIGPlus_template_directive">The %template directive</a>
<li><a href="#SWIGPlus_template_functions">Function templates</a>
<li><a href="#SWIGPlus_template_classes">Default template arguments</a>
<li><a href="#SWIGPlus_template_class_inheritance">Template base classes</a>
<li><a href="#SWIGPlus_template_specialization">Template specialization</a>
<li><a href="#SWIGPlus_template_member">Member templates</a>
<li><a href="#SWIGPlus_template_more">More on templates</a>
</ul>
<li><a href="#SWIGPlus_namespaces">Namespaces</a> <li><a href="#SWIGPlus_namespaces">Namespaces</a>
<ul> <ul>
<li><a href="#SWIGPlus_nspace">The nspace feature for namespaces</a> <li><a href="#SWIGPlus_nspace">The nspace feature for namespaces</a>
@ -2936,23 +2945,24 @@ as <tt>vector&lt;int&gt;</tt>. The wrapper for <tt>foo()</tt> will
accept either variant. accept either variant.
</p> </p>
<H3><a name="SWIGPlus_template_directive">6.18.1 The %template directive</a></H3>
<p> <p>
Starting with SWIG-1.3.7, simple C++ template declarations can also be There are a couple of important points about template wrapping.
wrapped. SWIG-1.3.12 greatly expands upon the earlier implementation. Before discussing this any further, there are a few things First, a bare C++ template
you need to know about template wrapping. First, a bare C++ template
does not define any sort of runnable object-code for which SWIG can does not define any sort of runnable object-code for which SWIG can
normally create a wrapper. Therefore, in order to wrap a template, normally create a wrapper. Therefore, in order to wrap a template,
you need to give SWIG information about a particular template you need to give SWIG information about a particular template
instantiation (e.g., <tt>vector&lt;int&gt;</tt>, instantiation (e.g., <tt>vector&lt;int&gt;</tt>,
<tt>array&lt;double&gt;</tt>, etc.). Second, an instantiation name <tt>array&lt;double&gt;</tt>, etc.). Second, an instantiation name
such as <tt>vector&lt;int&gt;</tt> is generally not a valid identifier such as <tt>vector&lt;int&gt;</tt> is generally not a valid identifier
name in most target languages. Thus, you will need to give the name in most target languages. Thus, you will need to give the
template instantiation a more suitable name such as <tt>intvector</tt> template instantiation a more suitable name such as <tt>intvector</tt>.
when creating a wrapper.
</p> </p>
<p> <p>
To illustrate, consider the following template definition: To illustrate, consider the following class template definition:
</p> </p>
<div class="code"><pre> <div class="code"><pre>
@ -2985,14 +2995,26 @@ public:
</pre></div> </pre></div>
<p> <p>
By itself, this template declaration is useless--SWIG simply ignores it By itself, this class template is useless--SWIG simply ignores it
because it doesn't know how to generate any code until unless a definition of because it doesn't know how to generate any code unless a definition of
<tt>T</tt> is provided. <tt>T</tt> is provided.
The <tt>%template</tt> directive is required to instantiate the template for use in a target language.
The directive requires an identifier name for use in the target language plus the template for instantiation.
The example below instantiates <tt>List&lt;int&gt;</tt> for use as a class named <tt>intList</tt>:
</p> </p>
<div class="code">
<pre>
%template(intList) List&lt;int&gt;;
</pre>
</div>
<p> <p>
One way to create wrappers for a specific template instantiation is to simply The instantiation expands the template code as a C++ compiler would do and then makes it available
provide an expanded version of the class directly like this: under the given identifier name.
Essentially it is the same as wrapping the following concept code where
the class template definition has <tt>T</TT> expanded to <tt>int</tt>
(note that this is not entirely valid syntax):
</p> </p>
<div class="code"> <div class="code">
@ -3014,28 +3036,6 @@ public:
</div> </div>
<p>
The <tt>%rename</tt> directive is needed to give the template class an appropriate identifier
name in the target language (most languages would not recognize C++ template syntax as a valid
class name). The rest of the code is the same as what would appear in a normal
class definition.
</p>
<p>
Since manual expansion of templates gets old in a hurry, the <tt>%template</tt> directive can
be used to create instantiations of a template class. Semantically, <tt>%template</tt> is
simply a shortcut---it expands template code in exactly the same way as shown above. Here
are some examples:
</p>
<div class="code">
<pre>
/* Instantiate a few different versions of the template */
%template(intList) List&lt;int&gt;;
%template(doubleList) List&lt;double&gt;;
</pre>
</div>
<p> <p>
The argument to <tt>%template()</tt> is the name of the instantiation The argument to <tt>%template()</tt> is the name of the instantiation
in the target language. The name you choose should not conflict with in the target language. The name you choose should not conflict with
@ -3053,7 +3053,67 @@ typedef List&lt;int&gt; intList; // OK
</div> </div>
<p> <p>
SWIG can also generate wrappers for function templates using a similar technique. The <tt>%template</tt> directive
must always appear <em>after</em> the definition of the template to be expanded, so the following will work:
</p>
<div class="code">
<pre>
template&lt;class T&gt; class List { ... };
%template(intList) List&lt;int&gt;;
</pre>
</div>
<p>
but if %template is used before the template definition, such as:
</p>
<div class="code">
<pre>
%template(intList) List&lt;int&gt;;
template&lt;class T&gt; class List { ... };
</pre>
</div>
<p>
SWIG will generate an error:
</p>
<div class="shell">
<pre>
example.i:3: Error: Template 'List' undefined.
</pre>
</div>
<p>
Since the type system knows how to handle <tt>typedef</tt>, it is
generally not necessary to instantiate different versions of a template
for typenames that are equivalent. For instance, consider this code:
</p>
<div class="code">
<pre>
%template(intList) List&lt;int&gt;;
typedef int Integer;
...
void foo(List&lt;Integer&gt; *x);
</pre>
</div>
<p>
In this case, <tt>List&lt;Integer&gt;</tt> is exactly the same type as
<tt>List&lt;int&gt;</tt>. Any use of <tt>List&lt;Integer&gt;</tt> is mapped back to the
instantiation of <tt>List&lt;int&gt;</tt> created earlier. Therefore, it is
not necessary to instantiate a new class for the type <tt>Integer</tt> (doing so is
redundant and will simply result in code bloat).
</p>
<H3><a name="SWIGPlus_template_functions">6.18.2 Function templates</a></H3>
<p>
SWIG can also generate wrappers for function templates using a similar technique
to that shown above for class templates.
For example: For example:
</p> </p>
@ -3073,6 +3133,28 @@ In this case, <tt>maxint</tt> and <tt>maxdouble</tt> become unique names for spe
instantiations of the function. instantiations of the function.
</p> </p>
<p>
SWIG even supports overloaded templated functions. As usual the <tt>%template</tt> directive
is used to wrap templated functions. For example:
</p>
<div class="code">
<pre>
template&lt;class T&gt; void foo(T x) { };
template&lt;class T&gt; void foo(T x, T y) { };
%template(foo) foo&lt;int&gt;;
</pre>
</div>
<p>
This will generate two overloaded wrapper methods, the first will take a single integer as an argument
and the second will take two integer arguments.
</p>
<H3><a name="SWIGPlus_template_classes">6.18.3 Default template arguments</a></H3>
<p> <p>
The number of arguments supplied to <tt>%template</tt> should match that in the The number of arguments supplied to <tt>%template</tt> should match that in the
original template definition. Template default arguments are supported. For example: original template definition. Template default arguments are supported. For example:
@ -3110,28 +3192,8 @@ instantiation only once in order to reduce the potential for code
bloat. bloat.
</p> </p>
<p> <H3><a name="SWIGPlus_template_class_inheritance">6.18.4 Template base classes</a></H3>
Since the type system knows how to handle <tt>typedef</tt>, it is
generally not necessary to instantiate different versions of a template
for typenames that are equivalent. For instance, consider this code:
</p>
<div class="code">
<pre>
%template(intList) vector&lt;int&gt;;
typedef int Integer;
...
void foo(vector&lt;Integer&gt; *x);
</pre>
</div>
<p>
In this case, <tt>vector&lt;Integer&gt;</tt> is exactly the same type as
<tt>vector&lt;int&gt;</tt>. Any use of <tt>Vector&lt;Integer&gt;</tt> is mapped back to the
instantiation of <tt>vector&lt;int&gt;</tt> created earlier. Therefore, it is
not necessary to instantiate a new class for the type <tt>Integer</tt> (doing so is
redundant and will simply result in code bloat).
</p>
<p> <p>
When a template is instantiated using <tt>%template</tt>, information When a template is instantiated using <tt>%template</tt>, information
@ -3158,13 +3220,13 @@ nothing is known about <tt>List&lt;int&gt;</tt>, you will get a warning message
<div class="shell"> <div class="shell">
<pre> <pre>
example.h:42: Warning 401. Nothing known about class 'List&lt;int &gt;'. Ignored. example.h:42: Warning 401. Nothing known about class 'List&lt; int &gt;'. Ignored.
example.h:42: Warning 401. Maybe you forgot to instantiate 'List&lt;int &gt;' using %template. example.h:42: Warning 401. Maybe you forgot to instantiate 'List&lt; int &gt;' using %template.
</pre> </pre>
</div> </div>
<p> <p>
If a template class inherits from another template class, you need to If a class template inherits from another class template, you need to
make sure that base classes are instantiated before derived classes. make sure that base classes are instantiated before derived classes.
For example: For example:
</p> </p>
@ -3235,6 +3297,9 @@ TEMPLATE_WRAP(PairStringInt, std::pair&lt;string, int&gt;)
Note the use of a vararg macro for the type T. If this wasn't used, the comma in the templated type in the last example would not be possible. Note the use of a vararg macro for the type T. If this wasn't used, the comma in the templated type in the last example would not be possible.
</p> </p>
<H3><a name="SWIGPlus_template_specialization">6.18.5 Template specialization</a></H3>
<p> <p>
The SWIG template mechanism <em>does</em> support specialization. For instance, if you define The SWIG template mechanism <em>does</em> support specialization. For instance, if you define
a class like this, a class like this,
@ -3281,7 +3346,7 @@ private:
public: public:
List(int max); List(int max);
~List(); ~List();
void append(int obj); void append(T obj);
int length(); int length();
T get(int n); T get(int n);
}; };
@ -3322,10 +3387,13 @@ SWIG implements template argument deduction so that the following partial specia
</pre> </pre>
</div> </div>
<H3><a name="SWIGPlus_template_member">6.18.6 Member templates</a></H3>
<p> <p>
Member function templates are supported. The underlying principle is the same Member templates are supported. The underlying principle is the same
as for normal templates--SWIG can't create a wrapper unless you provide as for normal templates--SWIG can't create a wrapper unless you provide
more information about types. For example, a class with a member template might more information about types. For example, a class with a member function template might
look like this: look like this:
</p> </p>
@ -3399,11 +3467,6 @@ methods to the Foo class.
</p> </p>
<p>
Note: because of the way that templates are handled, the <tt>%template</tt> directive
must always appear <em>after</em> the definition of the template to be expanded.
</p>
<p> <p>
Now, if your target language supports overloading, you can even try Now, if your target language supports overloading, you can even try
</p> </p>
@ -3424,7 +3487,7 @@ depending on the argument type.
<p> <p>
When used with members, the <tt>%template</tt> directive may be placed in another When used with members, the <tt>%template</tt> directive may be placed in another
template class. Here is a slightly perverse example: class template. Here is a slightly perverse example:
</p> </p>
<div class="code"> <div class="code">
@ -3475,7 +3538,7 @@ template&lt;class T1, class T2&gt; struct pair {
<p> <p>
This declaration is perfectly acceptable to SWIG, but the constructor template will be ignored This declaration is perfectly acceptable to SWIG, but the constructor template will be ignored
unless you explicitly expand it. To do that, you could expand a few versions of the constructor unless you explicitly expand it. To do that, you could expand a few versions of the constructor
in the template class itself. For example: in the class template itself. For example:
</p> </p>
<div class="code"> <div class="code">
@ -3536,6 +3599,9 @@ constructor, that will dispatch the proper call depending on the argument
type. type.
</p> </p>
<H3><a name="SWIGPlus_template_more">6.18.7 More on templates</a></H3>
<p> <p>
If all of this isn't quite enough and you really want to make If all of this isn't quite enough and you really want to make
someone's head explode, SWIG directives such as someone's head explode, SWIG directives such as
@ -3568,7 +3634,7 @@ instantiation.
</p> </p>
<p> <p>
It is also possible to separate these declarations from the template class. For example: It is also possible to separate these declarations from the class template. For example:
</p> </p>
<div class="code"> <div class="code">
@ -3616,25 +3682,6 @@ additional methods to a specific instantiation. For example:
</pre> </pre>
</div> </div>
<p>
SWIG even supports overloaded templated functions. As usual the <tt>%template</tt> directive
is used to wrap templated functions. For example:
</p>
<div class="code">
<pre>
template&lt;class T&gt; void foo(T x) { };
template&lt;class T&gt; void foo(T x, T y) { };
%template(foo) foo&lt;int&gt;;
</pre>
</div>
<p>
This will generate two overloaded wrapper methods, the first will take a single integer as an argument
and the second will take two integer arguments.
</p>
<p> <p>
It is even possible to extend a class via <tt>%extend</tt> with template methods, for example: It is even possible to extend a class via <tt>%extend</tt> with template methods, for example:
</p> </p>
@ -3694,7 +3741,7 @@ For example:
<pre> <pre>
template &lt;class T&gt; class OuterTemplateClass {}; template &lt;class T&gt; class OuterTemplateClass {};
// The nested class OuterClass::InnerClass inherits from the template class // The nested class OuterClass::InnerClass inherits from the class template
// OuterTemplateClass&lt;OuterClass::InnerStruct&gt; and thus the template needs // OuterTemplateClass&lt;OuterClass::InnerStruct&gt; and thus the template needs
// to be expanded with %template before the OuterClass declaration. // to be expanded with %template before the OuterClass declaration.
%template(OuterTemplateClass_OuterClass__InnerStruct) %template(OuterTemplateClass_OuterClass__InnerStruct)
@ -4524,7 +4571,7 @@ for member pointers.
<p> <p>
In some C++ programs, objects are often encapsulated by smart-pointers In some C++ programs, objects are often encapsulated by smart-pointers
or proxy classes. This is sometimes done to implement automatic memory management (reference counting) or or proxy classes. This is sometimes done to implement automatic memory management (reference counting) or
persistence. Typically a smart-pointer is defined by a template class where persistence. Typically a smart-pointer is defined by a class template where
the <tt>-&gt;</tt> operator has been overloaded. This class is then wrapped the <tt>-&gt;</tt> operator has been overloaded. This class is then wrapped
around some other class. For example: around some other class. For example:
</p> </p>