Duplicate class template instantiations via %template changes
Named duplicate class template instantiations now issue a warning and are ignored. Duplicate empty class template instantiations are quietly ignored. The test cases are fixed for this new behaviour. This commit is a pre-requisite for the near future so that the Python builtin wrappers can correctly use the SwigType_namestr function without generating duplicate symbol names.
This commit is contained in:
parent
777fd2c280
commit
4729cf2b1f
16 changed files with 283 additions and 55 deletions
|
|
@ -260,6 +260,7 @@
|
|||
<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_empty">Empty template instantiation</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_scoping">Scoping and templates</a>
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
<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_empty">Empty template instantiation</a>
|
||||
<li><a href="#SWIGPlus_template_specialization">Template specialization</a>
|
||||
<li><a href="#SWIGPlus_template_member">Member templates</a>
|
||||
<li><a href="#SWIGPlus_template_scoping">Scoping and templates</a>
|
||||
|
|
@ -3261,10 +3262,28 @@ void foo(List<Integer> *x);
|
|||
In this case, <tt>List<Integer></tt> is exactly the same type as
|
||||
<tt>List<int></tt>. Any use of <tt>List<Integer></tt> is mapped back to the
|
||||
instantiation of <tt>List<int></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).
|
||||
not correct to instantiate a new class for the type <tt>Integer</tt>.
|
||||
An attempt to do so such as:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%template(intList) List<int>;
|
||||
%template(IntegerList) List<Integer>; // Ignored
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
will result in the duplicate instantiation being ignored with a warning:
|
||||
</p>
|
||||
|
||||
<div class="shell">
|
||||
<pre>
|
||||
example.i:48: Warning 404: Duplicate template instantiation of 'List< Integer >' with name 'IntegerList' ignored,
|
||||
example.i:47: Warning 404: previous instantiation of 'List< int >' with name 'intList'.
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The template provided to <tt>%template</tt> for instantiation must be the actual template and not a typedef to a template.
|
||||
</p>
|
||||
|
|
@ -3333,36 +3352,49 @@ original template definition. Template default arguments are supported. For ex
|
|||
|
||||
<div class="code">
|
||||
<pre>
|
||||
template vector<typename T, int max=100> class vector {
|
||||
template <typename T, int max=100> class vector {
|
||||
...
|
||||
};
|
||||
|
||||
%template(intvec) vector<int>; // OK
|
||||
%template(intvec) vector<int>; // OK
|
||||
%template(vec1000) vector<int, 1000>; // OK
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The <tt>%template</tt> directive should not be used to wrap the same
|
||||
template instantiation more than once in the same scope. This will
|
||||
generate an error. For example:
|
||||
template instantiation more than once. This also applies to default parameters
|
||||
where a template parameter specified in the instantiation is the same as the default parameter.
|
||||
For example:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%template(intList) List<int>;
|
||||
%template(Listint) List<int>; // Error. Template already wrapped.
|
||||
%template(vec) vector<double>; // OK
|
||||
%template(vec100) vector<double, 100>; // Ignored
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
This error is caused because the template expansion results in two
|
||||
identical classes with the same name. This generates a symbol table
|
||||
conflict. Besides, it probably more efficient to only wrap a specific
|
||||
instantiation only once in order to reduce the potential for code
|
||||
bloat.
|
||||
will warn:
|
||||
</p>
|
||||
|
||||
<div class="shell">
|
||||
<pre>
|
||||
example.i:59: Warning 404: Duplicate template instantiation of 'vector< double,100 >' with name 'vec100' ignored,
|
||||
example.i:58: Warning 404: previous instantiation of 'vector< double >' with name 'vec'.
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
If this was not ignored, the template expansion would result in two identical classes.
|
||||
An identical instantiation is only wrapped once in order to reduce code bloat.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Compatibility Note</b>: Versions prior to SWIG-4.2.0 would sometimes not detect and prevent duplicate
|
||||
instantiations, such as when the wrapped name was different.
|
||||
</p>
|
||||
<H3><a name="SWIGPlus_template_class_inheritance">6.18.4 Template base classes</a></H3>
|
||||
|
||||
|
||||
|
|
@ -3429,20 +3461,6 @@ code (and base classes need to be wrapped before derived classes).
|
|||
Don't worry--if you get the order wrong, SWIG should generate a warning message.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Occasionally, you may need to tell SWIG about base classes that are defined by templates,
|
||||
but which aren't supposed to be wrapped. Since SWIG is not able to automatically
|
||||
instantiate templates for this purpose, you must do it manually. To do this, simply
|
||||
use the empty template instantiation, that is, <tt>%template</tt> with no name. For example:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
// Instantiate traits<double, double>, but don't wrap it.
|
||||
%template() traits<double, double>;
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
If you have to instantiate a lot of different classes for many different types,
|
||||
you might consider writing a SWIG macro. For example:
|
||||
|
|
@ -3468,7 +3486,66 @@ TEMPLATE_WRAP(PairStringInt, std::pair<string, int>)
|
|||
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>
|
||||
|
||||
<H3><a name="SWIGPlus_template_specialization">6.18.5 Template specialization</a></H3>
|
||||
<H3><a name="SWIGPlus_template_empty">6.18.5 Empty template instantiation</a></H3>
|
||||
|
||||
|
||||
<p>
|
||||
Occasionally, you may need to tell SWIG about classes that are defined by templates,
|
||||
but which aren't supposed to be wrapped. Since SWIG is not able to automatically
|
||||
instantiate templates for this purpose, you must do it manually. To do this, simply
|
||||
use <tt>%template()</tt>, that is the empty template instantiation that omits providing a name. For example:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
template<typename T> struct Traits {
|
||||
typedef T type;
|
||||
};
|
||||
%}
|
||||
|
||||
%template() Traits<int>; // instantiate Traits<int>, but don't wrap it
|
||||
|
||||
void traitor(Traits<int>::type val);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Without a template instantiation, SWIG does not know that the first parameter to the <tt>traitor</tt>
|
||||
function is type int and passing an integer to this function from any target language won't work.
|
||||
The empty template instantiation adds the appropriate type information into SWIG's type system, without
|
||||
forcing one to wrap the <tt>Traits</tt> class.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Duplicate template instantiation are not allowed, as described in the
|
||||
<a href="#SWIGPlus_template_classes">Default template arguments</a> section above.
|
||||
There is one exception where a named template instantiation can be followed by an empty template instantiation.
|
||||
Duplicate empty template instantiations are silently ignored, unlike duplicate named template instantiations.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Unlike template class instantiations, template function instantiations must have a name.
|
||||
Consider the following:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
template<class T> T tfunc(T x) { };
|
||||
%template() tfunc<double>;
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The empty template instantiation will be ignored with:
|
||||
</p>
|
||||
|
||||
<div class="shell">
|
||||
<pre>
|
||||
example.i:9: Warning 519: %template() contains no name. Template method ignored: tfunc< double >(double)
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<H3><a name="SWIGPlus_template_specialization">6.18.6 Template specialization</a></H3>
|
||||
|
||||
|
||||
<p>
|
||||
|
|
@ -3558,7 +3635,7 @@ SWIG implements template argument deduction so that the following partial specia
|
|||
</pre>
|
||||
</div>
|
||||
|
||||
<H3><a name="SWIGPlus_template_member">6.18.6 Member templates</a></H3>
|
||||
<H3><a name="SWIGPlus_template_member">6.18.7 Member templates</a></H3>
|
||||
|
||||
|
||||
<p>
|
||||
|
|
@ -3770,7 +3847,7 @@ constructor, that will dispatch the proper call depending on the argument
|
|||
type.
|
||||
</p>
|
||||
|
||||
<H3><a name="SWIGPlus_template_scoping">6.18.7 Scoping and templates</a></H3>
|
||||
<H3><a name="SWIGPlus_template_scoping">6.18.8 Scoping and templates</a></H3>
|
||||
|
||||
|
||||
<p>
|
||||
|
|
@ -3871,7 +3948,7 @@ template class C<int>;
|
|||
</p>
|
||||
|
||||
|
||||
<H3><a name="SWIGPlus_template_more">6.18.8 More on templates</a></H3>
|
||||
<H3><a name="SWIGPlus_template_more">6.18.9 More on templates</a></H3>
|
||||
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -493,6 +493,7 @@ example.i(4) : Syntax error in input(1).
|
|||
<li>401. Nothing known about class 'name'. Ignored.
|
||||
<li>402. Base class 'name' is incomplete.
|
||||
<li>403. Class 'name' might be abstract.
|
||||
<li>404. Duplicate template instantiation of '<em>type</em>' with name '<em>name</em>' ignored, previous instantiation of '<em>type</em>' with name '<em>name</em>'.
|
||||
<li>450. Reserved
|
||||
<li>451. Setting const char * variable may leak memory.
|
||||
<li>452. Reserved
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue