Merge branch 'templates-scope-enforcement'
* templates-scope-enforcement: Test a few %template errors Add using declarations to templates into typedef table. Fix type lookup in the presence of using directives and using declarations More docs on %template Testcase fix for nameclash in php %template scope enforcement and class definition fixes Template documentation tweaks More consistent formatting of examples in documentation More consistent formatting of examples in documentation Documentation corrections to use targetlang formatting More consistent formatting of examples in documentation More consistent formatting of examples in documentation More consistent formatting of examples in documentation Namespace documentation minor corrections Improve description of template_parameters_resolve Minor code optimisation in template_parameters_resolve Fix scope lookup for template parameters containing unary scope operators Typemap change for templates
This commit is contained in:
commit
32a454cfef
51 changed files with 1924 additions and 700 deletions
|
|
@ -246,6 +246,16 @@
|
||||||
<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_scoping">Scoping and 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>
|
||||||
|
|
|
||||||
|
|
@ -639,7 +639,7 @@ public:
|
||||||
virtual ~FooBarAbstract() {};
|
virtual ~FooBarAbstract() {};
|
||||||
|
|
||||||
std::string FooBar() {
|
std::string FooBar() {
|
||||||
return this->Foo() + ", " + this->Bar();
|
return this->Foo() + ", " + this->Bar();
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -411,7 +411,7 @@ void print_array(double x[10]);
|
||||||
Now, in a scripting language, you might write this:
|
Now, in a scripting language, you might write this:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="code">
|
<div class="targetlang">
|
||||||
<pre>
|
<pre>
|
||||||
a = new_doubleArray(10) # Create an array
|
a = new_doubleArray(10) # Create an array
|
||||||
for i in range(0, 10):
|
for i in range(0, 10):
|
||||||
|
|
@ -475,7 +475,7 @@ void print_array(double x[10]);
|
||||||
Allows you to do this:
|
Allows you to do this:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="code">
|
<div class="targetlang">
|
||||||
<pre>
|
<pre>
|
||||||
import example
|
import example
|
||||||
c = example.doubleArray(10) # Create double[10]
|
c = example.doubleArray(10) # Create double[10]
|
||||||
|
|
@ -801,7 +801,7 @@ target language. In other words, if you were using a language like Tcl,
|
||||||
and you wrote this,
|
and you wrote this,
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="code">
|
<div class="targetlang">
|
||||||
<pre>
|
<pre>
|
||||||
% foo Hello
|
% foo Hello
|
||||||
</pre>
|
</pre>
|
||||||
|
|
@ -852,7 +852,7 @@ size_t parity(char *str, size_t len, size_t initial);
|
||||||
Now, in the target language, you can use binary string data like this:
|
Now, in the target language, you can use binary string data like this:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="code">
|
<div class="targetlang">
|
||||||
<pre>
|
<pre>
|
||||||
>>> s = "H\x00\x15eg\x09\x20"
|
>>> s = "H\x00\x15eg\x09\x20"
|
||||||
>>> parity(s, 0)
|
>>> parity(s, 0)
|
||||||
|
|
|
||||||
|
|
@ -1008,8 +1008,7 @@ The following operators cannot be overloaded (mainly because they are not suppor
|
||||||
<p>
|
<p>
|
||||||
SWIG also accepts the <tt>__str__()</tt> member function which converts an object to a string. This function should return a const char*, preferably to static memory. This will be used for the <tt>print()</tt> and <tt>tostring()</tt> functions in Lua. Assuming the complex class has a function
|
SWIG also accepts the <tt>__str__()</tt> member function which converts an object to a string. This function should return a const char*, preferably to static memory. This will be used for the <tt>print()</tt> and <tt>tostring()</tt> functions in Lua. Assuming the complex class has a function
|
||||||
</p>
|
</p>
|
||||||
<div class="code"><pre>const char* __str__()
|
<div class="code"><pre>const char* __str__() {
|
||||||
{
|
|
||||||
static char buffer[255];
|
static char buffer[255];
|
||||||
sprintf(buffer, "Complex(%g, %g)", this->re(), this->im());
|
sprintf(buffer, "Complex(%g, %g)", this->re(), this->im());
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
@ -1031,8 +1030,7 @@ Complex(10, 12)
|
||||||
<p>
|
<p>
|
||||||
It is also possible to overload the operator<tt>[]</tt>, but currently this cannot be automatically performed. To overload the operator<tt>[]</tt> you need to provide two functions, <tt>__getitem__()</tt> and <tt>__setitem__()</tt>
|
It is also possible to overload the operator<tt>[]</tt>, but currently this cannot be automatically performed. To overload the operator<tt>[]</tt> you need to provide two functions, <tt>__getitem__()</tt> and <tt>__setitem__()</tt>
|
||||||
</p>
|
</p>
|
||||||
<div class="code"><pre>class Complex
|
<div class="code"><pre>class Complex {
|
||||||
{
|
|
||||||
//....
|
//....
|
||||||
double __getitem__(int i)const; // i is the index, returns the data
|
double __getitem__(int i)const; // i is the index, returns the data
|
||||||
void __setitem__(int i, double d); // i is the index, d is the data
|
void __setitem__(int i, double d); // i is the index, d is the data
|
||||||
|
|
|
||||||
|
|
@ -1633,10 +1633,9 @@ class DoubleArray {
|
||||||
void setitem(int i, double val) {
|
void setitem(int i, double val) {
|
||||||
if ((i >= 0) && (i < n))
|
if ((i >= 0) && (i < n))
|
||||||
ptr[i] = val;
|
ptr[i] = val;
|
||||||
else {
|
else
|
||||||
throw RangeError();
|
throw RangeError();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -231,8 +231,7 @@ int fact(int n) {
|
||||||
}
|
}
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
/* testing for overflow would be a good idea here */
|
/* testing for overflow would be a good idea here */
|
||||||
return n * fact(n-1);
|
return n * fact(n-1);
|
||||||
}
|
}
|
||||||
|
|
@ -2476,8 +2475,9 @@ public:
|
||||||
Twit operator+ (const Twit& twit) const;
|
Twit operator+ (const Twit& twit) const;
|
||||||
|
|
||||||
// Forward to operator+
|
// Forward to operator+
|
||||||
Twit add (const Twit& twit) const
|
Twit add (const Twit& twit) const {
|
||||||
{ return *this + twit; }
|
return *this + twit;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,16 @@
|
||||||
<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_scoping">Scoping and 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,10 +2946,12 @@ as <tt>vector<int></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
|
||||||
|
|
@ -2947,12 +2959,11 @@ instantiation (e.g., <tt>vector<int></tt>,
|
||||||
<tt>array<double></tt>, etc.). Second, an instantiation name
|
<tt>array<double></tt>, etc.). Second, an instantiation name
|
||||||
such as <tt>vector<int></tt> is generally not a valid identifier
|
such as <tt>vector<int></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 +2996,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<int></tt> for use as a class named <tt>intList</tt>:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%template(intList) List<int>;
|
||||||
|
</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 +3037,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<int>;
|
|
||||||
%template(doubleList) List<double>;
|
|
||||||
</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 +3054,81 @@ typedef List<int> 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<class T> class List { ... };
|
||||||
|
%template(intList) List<int>;
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
but if %template is used before the template definition, such as:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%template(intList) List<int>;
|
||||||
|
template<class T> 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<int>;
|
||||||
|
typedef int Integer;
|
||||||
|
...
|
||||||
|
void foo(List<Integer> *x);
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The template provide to <tt>%template</tt> for instantiation must be the actual template and not a typedef to a template.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
typedef List<int> ListOfInt;
|
||||||
|
|
||||||
|
%template(intList) List<int>; // ok
|
||||||
|
%template(intList) ListOfInt; // illegal - Syntax error
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<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 +3148,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<class T> void foo(T x) { };
|
||||||
|
template<class T> void foo(T x, T y) { };
|
||||||
|
|
||||||
|
%template(foo) foo<int>;
|
||||||
|
</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 +3207,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<int>;
|
|
||||||
typedef int Integer;
|
|
||||||
...
|
|
||||||
void foo(vector<Integer> *x);
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
In this case, <tt>vector<Integer></tt> is exactly the same type as
|
|
||||||
<tt>vector<int></tt>. Any use of <tt>Vector<Integer></tt> is mapped back to the
|
|
||||||
instantiation of <tt>vector<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).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
When a template is instantiated using <tt>%template</tt>, information
|
When a template is instantiated using <tt>%template</tt>, information
|
||||||
|
|
@ -3164,7 +3241,7 @@ example.h:42: Warning 401. Maybe you forgot to instantiate 'List<int >' us
|
||||||
</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 +3312,9 @@ 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.
|
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 +3361,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 +3402,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 +3482,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 +3502,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 +3553,7 @@ template<class T1, class T2> 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 +3614,110 @@ constructor, that will dispatch the proper call depending on the argument
|
||||||
type.
|
type.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<H3><a name="SWIGPlus_template_scoping">6.18.7 Scoping and templates</a></H3>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The <tt>%template</tt> directive for a class template is the equivalent to an explicit instantiation
|
||||||
|
of a C++ class template. The scope for a valid <tt>%template</tt> instantiation is the same
|
||||||
|
as the scope required for a valid explicit instantiation of a C++ template.
|
||||||
|
A definition of the template for the explicit instantiation must be in scope
|
||||||
|
where the instantiation is declared and must not be enclosed within a different namespace.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For example, a few <tt>%template</tt> instantiations and C++ explicit instantiations are shown below:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
namespace N {
|
||||||
|
template<typename T> class C {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// valid
|
||||||
|
%template(cin) N::C<int>;
|
||||||
|
template class N::C<int>;
|
||||||
|
|
||||||
|
// valid
|
||||||
|
namespace N {
|
||||||
|
%template(cin) C<int>;
|
||||||
|
template class C<int>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// valid
|
||||||
|
using namespace N;
|
||||||
|
%template(cin) C<int>;
|
||||||
|
template class C<int>;
|
||||||
|
|
||||||
|
// valid
|
||||||
|
using N::C;
|
||||||
|
%template(cin) C<int>;
|
||||||
|
template class C<int>;
|
||||||
|
|
||||||
|
// ill-formed
|
||||||
|
namespace unrelated {
|
||||||
|
using N::C;
|
||||||
|
%template(cin) C<int>;
|
||||||
|
template class C<int>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ill-formed
|
||||||
|
namespace unrelated {
|
||||||
|
using namespace N;
|
||||||
|
%template(cin) C<int>;
|
||||||
|
template class C<int>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ill-formed
|
||||||
|
namespace unrelated {
|
||||||
|
namespace N {
|
||||||
|
%template(cin) C<int>;
|
||||||
|
template class C<int>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ill-formed
|
||||||
|
namespace unrelated {
|
||||||
|
%template(cin) N::C<int>;
|
||||||
|
template class N::C<int>;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
When the scope is incorrect, such as for the ill-formed examples above, an error occurs:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<pre>
|
||||||
|
cpp_template_scope.i:34: Error: 'C' resolves to 'N::C' and was incorrectly instantiated
|
||||||
|
in scope 'unrelated' instead of within scope 'N'.
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A note for the C++ standard geeks out there; a valid instantiation is one which conforms to
|
||||||
|
the C++03 standard as C++11 made a change to disallow using declarations and using directives to find a template.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
// valid C++03, ill-formed C++11
|
||||||
|
using N::C;
|
||||||
|
template class C<int>;
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<b>Compatibility Note</b>: Versions prior to SWIG-4.0.0 did not error out with incorrectly scoped
|
||||||
|
<tt>%template</tt> declarations, but this led to numerous subtle template scope problems.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<H3><a name="SWIGPlus_template_more">6.18.8 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 +3750,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 +3798,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<class T> void foo(T x) { };
|
|
||||||
template<class T> void foo(T x, T y) { };
|
|
||||||
|
|
||||||
%template(foo) foo<int>;
|
|
||||||
</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 +3857,7 @@ For example:
|
||||||
<pre>
|
<pre>
|
||||||
template <class T> class OuterTemplateClass {};
|
template <class T> class OuterTemplateClass {};
|
||||||
|
|
||||||
// The nested class OuterClass::InnerClass inherits from the template class
|
// The nested class OuterClass::InnerClass inherits from the class template
|
||||||
// OuterTemplateClass<OuterClass::InnerStruct> and thus the template needs
|
// OuterTemplateClass<OuterClass::InnerStruct> 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)
|
||||||
|
|
@ -3915,6 +4078,8 @@ then SWIG simply creates three wrapper functions <tt>bar()</tt>,
|
||||||
<tt>spam()</tt>, and <tt>blah()</tt> in the target language. SWIG
|
<tt>spam()</tt>, and <tt>blah()</tt> in the target language. SWIG
|
||||||
does not prepend the names with a namespace prefix nor are the
|
does not prepend the names with a namespace prefix nor are the
|
||||||
functions packaged in any kind of nested scope.
|
functions packaged in any kind of nested scope.
|
||||||
|
Note that the default handling of flattening all the namespace scopes in the target language
|
||||||
|
can be changed via the <a href="#SWIGPlus_nspace">nspace feature</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -4203,9 +4368,7 @@ namespace foo {
|
||||||
<p>
|
<p>
|
||||||
<b>Note:</b> The flattening of namespaces is only intended to serve as
|
<b>Note:</b> The flattening of namespaces is only intended to serve as
|
||||||
a basic namespace implementation.
|
a basic namespace implementation.
|
||||||
None of the target language modules are currently programmed
|
More advanced handling of namespaces is discussed next.
|
||||||
with any namespace awareness. In the future, language modules may or may not provide
|
|
||||||
more advanced namespace support.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<H3><a name="SWIGPlus_nspace">6.19.1 The nspace feature for namespaces</a></H3>
|
<H3><a name="SWIGPlus_nspace">6.19.1 The nspace feature for namespaces</a></H3>
|
||||||
|
|
@ -4524,7 +4687,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>-></tt> operator has been overloaded. This class is then wrapped
|
the <tt>-></tt> operator has been overloaded. This class is then wrapped
|
||||||
around some other class. For example:
|
around some other class. For example:
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
152
Examples/test-suite/class_scope_namespace.i
Normal file
152
Examples/test-suite/class_scope_namespace.i
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
// Test a mix of forward class declarations, class definitions, using declarations and using directives.
|
||||||
|
|
||||||
|
%module class_scope_namespace
|
||||||
|
|
||||||
|
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) H::HH;
|
||||||
|
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Space8::I::II;
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
struct A;
|
||||||
|
namespace Space1 {
|
||||||
|
namespace SubSpace1 {
|
||||||
|
struct A {
|
||||||
|
void aa(Space1::SubSpace1::A, SubSpace1::A, A) {}
|
||||||
|
};
|
||||||
|
void aaa(Space1::SubSpace1::A, SubSpace1::A, A) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Space2 {
|
||||||
|
struct B;
|
||||||
|
}
|
||||||
|
using Space2::B;
|
||||||
|
struct B {
|
||||||
|
void bb(Space2::B, B) {}
|
||||||
|
};
|
||||||
|
void bbb(Space2::B, B) {}
|
||||||
|
|
||||||
|
namespace Space3 {
|
||||||
|
namespace SubSpace3 {
|
||||||
|
struct C;
|
||||||
|
struct D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct C;
|
||||||
|
struct D;
|
||||||
|
namespace Space3 {
|
||||||
|
struct C;
|
||||||
|
struct SubSpace3::C {
|
||||||
|
void cc(Space3::SubSpace3::C, SubSpace3::C) {}
|
||||||
|
};
|
||||||
|
using SubSpace3::D;
|
||||||
|
struct SubSpace3::D {
|
||||||
|
void dd(Space3::SubSpace3::D, SubSpace3::D, D) {}
|
||||||
|
};
|
||||||
|
void ccc(Space3::SubSpace3::C, SubSpace3::C) {}
|
||||||
|
void ddd(Space3::SubSpace3::D, SubSpace3::D, D) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Space4 {
|
||||||
|
namespace SubSpace4 {
|
||||||
|
struct E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using namespace Space4;
|
||||||
|
using SubSpace4::E;
|
||||||
|
// Was added to incorrect namespace in swig-3.0.12
|
||||||
|
struct SubSpace4::E {
|
||||||
|
void ee(Space4::SubSpace4::E, SubSpace4::E, E) {}
|
||||||
|
};
|
||||||
|
void eee(Space4::SubSpace4::E, SubSpace4::E, E) {}
|
||||||
|
|
||||||
|
namespace Space5 {
|
||||||
|
namespace SubSpace5 {
|
||||||
|
namespace SubSubSpace5 {
|
||||||
|
struct F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace Space5 {
|
||||||
|
using namespace SubSpace5;
|
||||||
|
using SubSubSpace5::F;
|
||||||
|
// Was added to incorrect namespace in swig-3.0.12
|
||||||
|
struct SubSubSpace5::F {
|
||||||
|
void ff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {}
|
||||||
|
};
|
||||||
|
void fff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Space6 {
|
||||||
|
struct G;
|
||||||
|
namespace SubSpace6 {
|
||||||
|
struct G;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace Space6 {
|
||||||
|
struct SubSpace6::G {
|
||||||
|
void gg(Space6::SubSpace6::G, SubSpace6::G) {}
|
||||||
|
};
|
||||||
|
void ggg(Space6::SubSpace6::G, SubSpace6::G) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct HH;
|
||||||
|
struct H {
|
||||||
|
struct HH {
|
||||||
|
void hh(H::HH) {}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
void hhh(H::HH) {}
|
||||||
|
|
||||||
|
namespace Space8 {
|
||||||
|
struct II;
|
||||||
|
struct I {
|
||||||
|
struct II {
|
||||||
|
void ii(Space8::I::II, I::II) {}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
void iii(Space8::I::II, I::II) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct J;
|
||||||
|
namespace Space9 {
|
||||||
|
namespace SubSpace9 {
|
||||||
|
struct J {
|
||||||
|
void jj(Space9::SubSpace9::J, SubSpace9::J, J) {}
|
||||||
|
};
|
||||||
|
void jjj(Space9::SubSpace9::J, SubSpace9::J, J) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Space10 {
|
||||||
|
struct K;
|
||||||
|
}
|
||||||
|
namespace Space10 {
|
||||||
|
namespace SubSpace10 {
|
||||||
|
struct K {
|
||||||
|
void kk(Space10::SubSpace10::K, SubSpace10::K, K) {}
|
||||||
|
};
|
||||||
|
void kkk(Space10::SubSpace10::K, SubSpace10::K, K) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace OtherSpace {
|
||||||
|
struct L;
|
||||||
|
struct M;
|
||||||
|
}
|
||||||
|
using OtherSpace::L;
|
||||||
|
namespace Space11 {
|
||||||
|
using OtherSpace::M;
|
||||||
|
namespace SubSpace11 {
|
||||||
|
struct L {
|
||||||
|
void ll(Space11::SubSpace11::L, SubSpace11::L, L) {}
|
||||||
|
};
|
||||||
|
void lll(Space11::SubSpace11::L, SubSpace11::L, L) {}
|
||||||
|
struct M {
|
||||||
|
void mm(Space11::SubSpace11::M, SubSpace11::M, M) {}
|
||||||
|
};
|
||||||
|
void mmm(Space11::SubSpace11::M, SubSpace11::M, M) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
|
@ -136,6 +136,7 @@ CPP_TEST_CASES += \
|
||||||
char_binary \
|
char_binary \
|
||||||
char_strings \
|
char_strings \
|
||||||
chartest \
|
chartest \
|
||||||
|
class_scope_namespace \
|
||||||
class_forward \
|
class_forward \
|
||||||
class_ignore \
|
class_ignore \
|
||||||
class_scope_weird \
|
class_scope_weird \
|
||||||
|
|
@ -291,6 +292,7 @@ CPP_TEST_CASES += \
|
||||||
multiple_inheritance_shared_ptr \
|
multiple_inheritance_shared_ptr \
|
||||||
name_cxx \
|
name_cxx \
|
||||||
name_warnings \
|
name_warnings \
|
||||||
|
namespace_chase \
|
||||||
namespace_class \
|
namespace_class \
|
||||||
namespace_enum \
|
namespace_enum \
|
||||||
namespace_extend \
|
namespace_extend \
|
||||||
|
|
@ -435,6 +437,7 @@ CPP_TEST_CASES += \
|
||||||
template_methods \
|
template_methods \
|
||||||
template_namespace_forward_declaration \
|
template_namespace_forward_declaration \
|
||||||
template_using_directive_and_declaration_forward \
|
template_using_directive_and_declaration_forward \
|
||||||
|
template_using_directive_typedef \
|
||||||
template_nested \
|
template_nested \
|
||||||
template_nested_typemaps \
|
template_nested_typemaps \
|
||||||
template_ns \
|
template_ns \
|
||||||
|
|
@ -445,6 +448,7 @@ CPP_TEST_CASES += \
|
||||||
template_ns_enum2 \
|
template_ns_enum2 \
|
||||||
template_ns_inherit \
|
template_ns_inherit \
|
||||||
template_ns_scope \
|
template_ns_scope \
|
||||||
|
template_parameters_global_scope \
|
||||||
template_partial_arg \
|
template_partial_arg \
|
||||||
template_partial_specialization \
|
template_partial_specialization \
|
||||||
template_partial_specialization_typedef \
|
template_partial_specialization_typedef \
|
||||||
|
|
|
||||||
26
Examples/test-suite/errors/cpp_class_definition.i
Normal file
26
Examples/test-suite/errors/cpp_class_definition.i
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
%module xxx
|
||||||
|
|
||||||
|
// This should error but doesn't
|
||||||
|
#if 0
|
||||||
|
namespace OtherSpace {
|
||||||
|
struct L;
|
||||||
|
}
|
||||||
|
namespace Space11 {
|
||||||
|
namespace SubSpace11 {
|
||||||
|
using OtherSpace::L;
|
||||||
|
struct L {
|
||||||
|
void ll();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Space1 {
|
||||||
|
struct A;
|
||||||
|
}
|
||||||
|
namespace Space2 {
|
||||||
|
struct Space1::A {
|
||||||
|
void x();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
1
Examples/test-suite/errors/cpp_class_definition.stderr
Normal file
1
Examples/test-suite/errors/cpp_class_definition.stderr
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
cpp_class_definition.i:22: Error: 'Space1::A' resolves to 'Space1::A' and was incorrectly instantiated in scope 'Space2' instead of within scope 'Space1'.
|
||||||
9
Examples/test-suite/errors/cpp_invalid_template.i
Normal file
9
Examples/test-suite/errors/cpp_invalid_template.i
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
%module cpp_invalid_scope
|
||||||
|
|
||||||
|
%template(abc) SSS::AAA<int>;
|
||||||
|
|
||||||
|
namespace UUU {
|
||||||
|
struct JJJ;
|
||||||
|
}
|
||||||
|
|
||||||
|
%template(xxx) UUU::JJJ<int>;
|
||||||
3
Examples/test-suite/errors/cpp_invalid_template.stderr
Normal file
3
Examples/test-suite/errors/cpp_invalid_template.stderr
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
cpp_invalid_template.i:3: Error: Undefined scope 'SSS'
|
||||||
|
cpp_invalid_template.i:3: Error: Template 'SSS::AAA' undefined.
|
||||||
|
cpp_invalid_template.i:9: Error: 'JJJ' is not defined as a template. (classforward)
|
||||||
40
Examples/test-suite/errors/cpp_namespace_template_bad.i
Normal file
40
Examples/test-suite/errors/cpp_namespace_template_bad.i
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
%module namespace_template
|
||||||
|
|
||||||
|
namespace test {
|
||||||
|
template<typename T> T max(T a, T b) { return (a > b) ? a : b; }
|
||||||
|
template<typename T> class vector {
|
||||||
|
public:
|
||||||
|
vector() { }
|
||||||
|
~vector() { }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test2 {
|
||||||
|
using namespace test;
|
||||||
|
%template(maxshort) max<short>;
|
||||||
|
%template(vectorshort) vector<short>;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test3 {
|
||||||
|
using test::max;
|
||||||
|
using test::vector;
|
||||||
|
%template(maxlong) max<long>;
|
||||||
|
%template(vectorlong) vector<long>;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test4 {
|
||||||
|
using namespace test;
|
||||||
|
typedef int Integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test4 {
|
||||||
|
%template(maxInteger) max<Integer>;
|
||||||
|
%template(vectorInteger) vector<Integer>;
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace test;
|
||||||
|
namespace test5 {
|
||||||
|
%template(maxdouble) max<double>;
|
||||||
|
%template(vectordouble) vector<double>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
cpp_namespace_template_bad.i:14: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test2' instead of within scope 'test'.
|
||||||
|
cpp_namespace_template_bad.i:15: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test2' instead of within scope 'test'.
|
||||||
|
cpp_namespace_template_bad.i:21: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test3' instead of within scope 'test'.
|
||||||
|
cpp_namespace_template_bad.i:22: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test3' instead of within scope 'test'.
|
||||||
|
cpp_namespace_template_bad.i:31: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test4' instead of within scope 'test'.
|
||||||
|
cpp_namespace_template_bad.i:32: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test4' instead of within scope 'test'.
|
||||||
|
cpp_namespace_template_bad.i:37: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test5' instead of within scope 'test'.
|
||||||
|
cpp_namespace_template_bad.i:37: Error: Template 'max' undefined.
|
||||||
|
cpp_namespace_template_bad.i:38: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test5' instead of within scope 'test'.
|
||||||
|
|
@ -1,2 +1,4 @@
|
||||||
|
cpp_nested_template.i:9: Error: 'Temply' resolves to '::Temply' and was incorrectly instantiated in scope 'A' instead of within scope ''.
|
||||||
cpp_nested_template.i:9: Warning 324: Named nested template instantiations not supported. Processing as if no name was given to %template().
|
cpp_nested_template.i:9: Warning 324: Named nested template instantiations not supported. Processing as if no name was given to %template().
|
||||||
|
cpp_nested_template.i:18: Error: 'Temply' resolves to '::Temply' and was incorrectly instantiated in scope 'B' instead of within scope ''.
|
||||||
cpp_nested_template.i:18: Warning 324: Named nested template instantiations not supported. Processing as if no name was given to %template().
|
cpp_nested_template.i:18: Warning 324: Named nested template instantiations not supported. Processing as if no name was given to %template().
|
||||||
|
|
|
||||||
57
Examples/test-suite/errors/cpp_template_scope.i
Normal file
57
Examples/test-suite/errors/cpp_template_scope.i
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
%module xxx
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template<typename T> class vector {};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S1 {};
|
||||||
|
struct S2 {};
|
||||||
|
struct S3 {};
|
||||||
|
struct S4 {};
|
||||||
|
struct S5 {};
|
||||||
|
struct S6 {};
|
||||||
|
struct S7 {};
|
||||||
|
|
||||||
|
// valid
|
||||||
|
namespace std {
|
||||||
|
%template(vi1) vector<S1>;
|
||||||
|
template class vector<S1>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// valid
|
||||||
|
using namespace std;
|
||||||
|
%template(vi2) vector<S2>;
|
||||||
|
template class vector<S2>;
|
||||||
|
|
||||||
|
// valid
|
||||||
|
using std::vector;
|
||||||
|
%template(vi3) vector<S3>;
|
||||||
|
template class vector<S3>;
|
||||||
|
|
||||||
|
// ill-formed
|
||||||
|
namespace unrelated {
|
||||||
|
using std::vector;
|
||||||
|
%template(vi4) vector<S4>;
|
||||||
|
template class vector<S4>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ill-formed
|
||||||
|
namespace unrelated {
|
||||||
|
using namespace std;
|
||||||
|
%template(vi5) vector<S5>;
|
||||||
|
template class vector<S5>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ill-formed
|
||||||
|
namespace unrelated {
|
||||||
|
namespace std {
|
||||||
|
%template(vi6) vector<S6>;
|
||||||
|
template class vector<S6>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ill-formed
|
||||||
|
namespace unrelated {
|
||||||
|
%template(vi7) std::vector<S7>;
|
||||||
|
template class std::vector<S7>;
|
||||||
|
}
|
||||||
11
Examples/test-suite/errors/cpp_template_scope.stderr
Normal file
11
Examples/test-suite/errors/cpp_template_scope.stderr
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
cpp_template_scope.i:18: Warning 320: Explicit template instantiation ignored.
|
||||||
|
cpp_template_scope.i:24: Warning 320: Explicit template instantiation ignored.
|
||||||
|
cpp_template_scope.i:29: Warning 320: Explicit template instantiation ignored.
|
||||||
|
cpp_template_scope.i:34: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
|
||||||
|
cpp_template_scope.i:35: Warning 320: Explicit template instantiation ignored.
|
||||||
|
cpp_template_scope.i:41: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
|
||||||
|
cpp_template_scope.i:42: Warning 320: Explicit template instantiation ignored.
|
||||||
|
cpp_template_scope.i:48: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated::std' instead of within scope 'std'.
|
||||||
|
cpp_template_scope.i:49: Warning 320: Explicit template instantiation ignored.
|
||||||
|
cpp_template_scope.i:55: Error: 'std::vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
|
||||||
|
cpp_template_scope.i:56: Warning 320: Explicit template instantiation ignored.
|
||||||
59
Examples/test-suite/java/class_scope_namespace_runme.java
Normal file
59
Examples/test-suite/java/class_scope_namespace_runme.java
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
|
||||||
|
import class_scope_namespace.*;
|
||||||
|
|
||||||
|
public class class_scope_namespace_runme {
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("class_scope_namespace");
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String argv[])
|
||||||
|
{
|
||||||
|
A a = new A();
|
||||||
|
B b = new B();
|
||||||
|
C c = new C();
|
||||||
|
D d = new D();
|
||||||
|
E e = new E();
|
||||||
|
F f = new F();
|
||||||
|
G g = new G();
|
||||||
|
H.HH h = new H.HH();
|
||||||
|
I.II i = new I.II();
|
||||||
|
J j = new J();
|
||||||
|
K k = new K();
|
||||||
|
L l = new L();
|
||||||
|
M m = new M();
|
||||||
|
|
||||||
|
a.aa(a, a, a);
|
||||||
|
b.bb(b, b);
|
||||||
|
c.cc(c, c);
|
||||||
|
d.dd(d, d, d);
|
||||||
|
e.ee(e, e, e);
|
||||||
|
f.ff(f, f, f, f);
|
||||||
|
g.gg(g, g);
|
||||||
|
h.hh(h);
|
||||||
|
i.ii(i, i);
|
||||||
|
j.jj(j, j, j);
|
||||||
|
k.kk(k, k, k);
|
||||||
|
l.ll(l, l, l);
|
||||||
|
m.mm(m, m, m);
|
||||||
|
|
||||||
|
class_scope_namespace.aaa(a, a, a);
|
||||||
|
class_scope_namespace.bbb(b, b);
|
||||||
|
class_scope_namespace.ccc(c, c);
|
||||||
|
class_scope_namespace.ddd(d, d, d);
|
||||||
|
class_scope_namespace.eee(e, e, e);
|
||||||
|
class_scope_namespace.fff(f, f, f, f);
|
||||||
|
class_scope_namespace.ggg(g, g);
|
||||||
|
class_scope_namespace.hhh(h);
|
||||||
|
class_scope_namespace.iii(i, i);
|
||||||
|
class_scope_namespace.jjj(j, j, j);
|
||||||
|
class_scope_namespace.kkk(k, k, k);
|
||||||
|
class_scope_namespace.lll(l, l, l);
|
||||||
|
class_scope_namespace.mmm(m, m, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
Examples/test-suite/java/cpp11_template_typedefs_runme.java
Normal file
19
Examples/test-suite/java/cpp11_template_typedefs_runme.java
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import cpp11_template_typedefs.*;
|
||||||
|
|
||||||
|
public class cpp11_template_typedefs_runme {
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("cpp11_template_typedefs");
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String argv[]) {
|
||||||
|
int alloc1 = cpp11_template_typedefs.get_bucket_allocator1();
|
||||||
|
int alloc2 = cpp11_template_typedefs.get_bucket_allocator2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
26
Examples/test-suite/java/namespace_chase_runme.java
Normal file
26
Examples/test-suite/java/namespace_chase_runme.java
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
import namespace_chase.*;
|
||||||
|
|
||||||
|
public class namespace_chase_runme {
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("namespace_chase");
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String argv[])
|
||||||
|
{
|
||||||
|
Struct1A s1a = new Struct1A();
|
||||||
|
Struct1B s1b = new Struct1B();
|
||||||
|
Struct1C s1c = new Struct1C();
|
||||||
|
|
||||||
|
namespace_chase.sss3a(s1a, s1b, s1c);
|
||||||
|
namespace_chase.sss3b(s1a, s1b, s1c);
|
||||||
|
// needs fixing
|
||||||
|
// namespace_chase.sss3c(s1a, s1b, s1c);
|
||||||
|
}
|
||||||
|
}
|
||||||
32
Examples/test-suite/java/namespace_template_runme.java
Normal file
32
Examples/test-suite/java/namespace_template_runme.java
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
import namespace_template.*;
|
||||||
|
|
||||||
|
public class namespace_template_runme {
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("namespace_template");
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String argv[]) {
|
||||||
|
vectorchar vc = new vectorchar();
|
||||||
|
vectorshort vs = new vectorshort();
|
||||||
|
vectorint vi = new vectorint();
|
||||||
|
vectorlong vl = new vectorlong();
|
||||||
|
|
||||||
|
vc.blah((char)10);
|
||||||
|
vs.blah((short)10);
|
||||||
|
vi.blah(10);
|
||||||
|
vl.blah(10);
|
||||||
|
|
||||||
|
vc.vectoruse(vc, vc);
|
||||||
|
vs.vectoruse(vs, vs);
|
||||||
|
vi.vectoruse(vi, vi);
|
||||||
|
vl.vectoruse(vl, vl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
import template_parameters_global_scope.*;
|
||||||
|
|
||||||
|
public class template_parameters_global_scope_runme {
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("template_parameters_global_scope");
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String argv[]) {
|
||||||
|
|
||||||
|
int alloc = 0;
|
||||||
|
|
||||||
|
// Check 1
|
||||||
|
alloc = template_parameters_global_scope.Bucket1();
|
||||||
|
alloc = template_parameters_global_scope.Bucket2();
|
||||||
|
alloc = template_parameters_global_scope.Bucket3();
|
||||||
|
alloc = template_parameters_global_scope.Bucket4();
|
||||||
|
alloc = template_parameters_global_scope.Bucket5();
|
||||||
|
alloc = template_parameters_global_scope.Bucket6();
|
||||||
|
|
||||||
|
// Check 2
|
||||||
|
alloc = template_parameters_global_scope.Spade1();
|
||||||
|
alloc = template_parameters_global_scope.Spade2();
|
||||||
|
alloc = template_parameters_global_scope.Spade3();
|
||||||
|
alloc = template_parameters_global_scope.Spade4();
|
||||||
|
alloc = template_parameters_global_scope.Spade5();
|
||||||
|
alloc = template_parameters_global_scope.Spade6();
|
||||||
|
|
||||||
|
// Check 3
|
||||||
|
alloc = template_parameters_global_scope.Ball1();
|
||||||
|
alloc = template_parameters_global_scope.Ball2();
|
||||||
|
alloc = template_parameters_global_scope.Ball3();
|
||||||
|
alloc = template_parameters_global_scope.Ball4();
|
||||||
|
alloc = template_parameters_global_scope.Ball5();
|
||||||
|
alloc = template_parameters_global_scope.Ball6();
|
||||||
|
|
||||||
|
// Check 4
|
||||||
|
alloc = template_parameters_global_scope.Bat1();
|
||||||
|
alloc = template_parameters_global_scope.Bat2();
|
||||||
|
alloc = template_parameters_global_scope.Bat3();
|
||||||
|
alloc = template_parameters_global_scope.Bat4();
|
||||||
|
alloc = template_parameters_global_scope.Bat5();
|
||||||
|
alloc = template_parameters_global_scope.Bat6();
|
||||||
|
|
||||||
|
// Check 5
|
||||||
|
alloc = template_parameters_global_scope.Chair1();
|
||||||
|
alloc = template_parameters_global_scope.Chair2();
|
||||||
|
alloc = template_parameters_global_scope.Chair3();
|
||||||
|
alloc = template_parameters_global_scope.Chair4();
|
||||||
|
alloc = template_parameters_global_scope.Chair5();
|
||||||
|
alloc = template_parameters_global_scope.Chair6();
|
||||||
|
|
||||||
|
// Check 6
|
||||||
|
alloc = template_parameters_global_scope.Table1();
|
||||||
|
alloc = template_parameters_global_scope.Table2();
|
||||||
|
alloc = template_parameters_global_scope.Table3();
|
||||||
|
alloc = template_parameters_global_scope.Table4();
|
||||||
|
alloc = template_parameters_global_scope.Table5();
|
||||||
|
alloc = template_parameters_global_scope.Table6();
|
||||||
|
|
||||||
|
/*
|
||||||
|
alloc = template_parameters_global_scope.rejig1();
|
||||||
|
alloc = template_parameters_global_scope.rejig2();
|
||||||
|
alloc = template_parameters_global_scope.rejig3();
|
||||||
|
alloc = template_parameters_global_scope.rejig4();
|
||||||
|
alloc = template_parameters_global_scope.rejig5();
|
||||||
|
alloc = template_parameters_global_scope.rejig6();
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,32 +19,32 @@ public class template_using_directive_and_declaration_forward_runme {
|
||||||
template_using_directive_and_declaration_forward.useit1b(new Thing1Int());
|
template_using_directive_and_declaration_forward.useit1b(new Thing1Int());
|
||||||
template_using_directive_and_declaration_forward.useit1c(new Thing1Int());
|
template_using_directive_and_declaration_forward.useit1c(new Thing1Int());
|
||||||
|
|
||||||
//BROKEN template_using_directive_and_declaration_forward.useit2(new Thing2Int());
|
template_using_directive_and_declaration_forward.useit2(new Thing2Int());
|
||||||
template_using_directive_and_declaration_forward.useit2a(new Thing2Int());
|
template_using_directive_and_declaration_forward.useit2a(new Thing2Int());
|
||||||
template_using_directive_and_declaration_forward.useit2b(new Thing2Int());
|
template_using_directive_and_declaration_forward.useit2b(new Thing2Int());
|
||||||
template_using_directive_and_declaration_forward.useit2c(new Thing2Int());
|
template_using_directive_and_declaration_forward.useit2c(new Thing2Int());
|
||||||
template_using_directive_and_declaration_forward.useit2d(new Thing2Int());
|
template_using_directive_and_declaration_forward.useit2d(new Thing2Int());
|
||||||
|
|
||||||
//BROKEN template_using_directive_and_declaration_forward.useit3(new Thing3Int());
|
template_using_directive_and_declaration_forward.useit3(new Thing3Int());
|
||||||
template_using_directive_and_declaration_forward.useit3a(new Thing3Int());
|
template_using_directive_and_declaration_forward.useit3a(new Thing3Int());
|
||||||
template_using_directive_and_declaration_forward.useit3b(new Thing3Int());
|
template_using_directive_and_declaration_forward.useit3b(new Thing3Int());
|
||||||
template_using_directive_and_declaration_forward.useit3c(new Thing3Int());
|
template_using_directive_and_declaration_forward.useit3c(new Thing3Int());
|
||||||
template_using_directive_and_declaration_forward.useit3d(new Thing3Int());
|
template_using_directive_and_declaration_forward.useit3d(new Thing3Int());
|
||||||
|
|
||||||
//BROKEN template_using_directive_and_declaration_forward.useit4(new Thing4Int());
|
template_using_directive_and_declaration_forward.useit4(new Thing4Int());
|
||||||
template_using_directive_and_declaration_forward.useit4a(new Thing4Int());
|
template_using_directive_and_declaration_forward.useit4a(new Thing4Int());
|
||||||
template_using_directive_and_declaration_forward.useit4b(new Thing4Int());
|
template_using_directive_and_declaration_forward.useit4b(new Thing4Int());
|
||||||
template_using_directive_and_declaration_forward.useit4c(new Thing4Int());
|
template_using_directive_and_declaration_forward.useit4c(new Thing4Int());
|
||||||
template_using_directive_and_declaration_forward.useit4d(new Thing4Int());
|
template_using_directive_and_declaration_forward.useit4d(new Thing4Int());
|
||||||
|
|
||||||
//BROKEN template_using_directive_and_declaration_forward.useit5(new Thing5Int());
|
template_using_directive_and_declaration_forward.useit5(new Thing5Int());
|
||||||
template_using_directive_and_declaration_forward.useit5a(new Thing5Int());
|
template_using_directive_and_declaration_forward.useit5a(new Thing5Int());
|
||||||
template_using_directive_and_declaration_forward.useit5b(new Thing5Int());
|
template_using_directive_and_declaration_forward.useit5b(new Thing5Int());
|
||||||
template_using_directive_and_declaration_forward.useit5c(new Thing5Int());
|
template_using_directive_and_declaration_forward.useit5c(new Thing5Int());
|
||||||
template_using_directive_and_declaration_forward.useit5d(new Thing5Int());
|
template_using_directive_and_declaration_forward.useit5d(new Thing5Int());
|
||||||
|
|
||||||
|
|
||||||
//BROKEN template_using_directive_and_declaration_forward.useit7(new Thing7Int());
|
template_using_directive_and_declaration_forward.useit7(new Thing7Int());
|
||||||
template_using_directive_and_declaration_forward.useit7a(new Thing7Int());
|
template_using_directive_and_declaration_forward.useit7a(new Thing7Int());
|
||||||
template_using_directive_and_declaration_forward.useit7b(new Thing7Int());
|
template_using_directive_and_declaration_forward.useit7b(new Thing7Int());
|
||||||
template_using_directive_and_declaration_forward.useit7c(new Thing7Int());
|
template_using_directive_and_declaration_forward.useit7c(new Thing7Int());
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
import template_using_directive_typedef.*;
|
||||||
|
|
||||||
|
public class template_using_directive_typedef_runme {
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("template_using_directive_typedef");
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String argv[]) {
|
||||||
|
Vector_Obj vo = new Vector_Obj();
|
||||||
|
|
||||||
|
Holder h = new Holder();
|
||||||
|
h.holder_use1(vo, vo, vo);
|
||||||
|
h.holder_use2(vo, vo, vo);
|
||||||
|
h.holder_use3(vo, vo, vo);
|
||||||
|
|
||||||
|
template_using_directive_typedef.tns_holder_use(vo, vo);
|
||||||
|
template_using_directive_typedef.tns_use(vo, vo, vo);
|
||||||
|
template_using_directive_typedef.global_holder_use(vo);
|
||||||
|
template_using_directive_typedef.global_use(vo, vo, vo);
|
||||||
|
template_using_directive_typedef.ns1_holder_use(vo);
|
||||||
|
template_using_directive_typedef.ns2_holder_use(vo, vo, vo, vo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
36
Examples/test-suite/namespace_chase.i
Normal file
36
Examples/test-suite/namespace_chase.i
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
%module namespace_chase
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
namespace Space1A {
|
||||||
|
struct Struct1A {};
|
||||||
|
namespace Space1B {
|
||||||
|
struct Struct1B {};
|
||||||
|
namespace Space1C {
|
||||||
|
struct Struct1C {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace Space2A {
|
||||||
|
using namespace Space1A;
|
||||||
|
namespace Space2B {
|
||||||
|
using namespace Space1B;
|
||||||
|
namespace Space2C {
|
||||||
|
using namespace Space1C;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace Space3 {
|
||||||
|
using namespace Space2A;
|
||||||
|
void sss3a(Space1A::Struct1A, Space1A::Space1B::Struct1B, Space1A::Space1B::Space1C::Struct1C) {}
|
||||||
|
void sss3b(Struct1A, Space1B::Struct1B, Space1B::Space1C::Struct1C) {}
|
||||||
|
// To fix: the last two parameters below fail and result in SWIGTYPE_ types instead of proxy classes
|
||||||
|
void sss3c(Space2A::Struct1A, Space2A::Space1B::Struct1B, Space2A::Space1B::Space1C::Struct1C) {}
|
||||||
|
}
|
||||||
|
namespace Space4 {
|
||||||
|
using namespace Space2A;
|
||||||
|
using namespace Space2A::Space2B;
|
||||||
|
using namespace Space2A::Space2B::Space2C;
|
||||||
|
void sss4a(Struct1A, Struct1B, Space2C::Struct1C) {}
|
||||||
|
void sss4b(Struct1A, Struct1B, Struct1C) {}
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
%module namespace_template
|
%module namespace_template
|
||||||
|
|
||||||
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) vector<int>; /* Ruby, wrong class name */
|
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector<int>; /* Ruby, wrong class name */
|
||||||
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test2::vector<short>; /* Ruby, wrong class name */
|
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector<short>; /* Ruby, wrong class name */
|
||||||
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test3::vector<long>; /* Ruby, wrong class name */
|
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector<long>; /* Ruby, wrong class name */
|
||||||
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) vector<test4::Integer>; /* Ruby, wrong class name */
|
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector<test::Char>; /* Ruby, wrong class name */
|
||||||
|
|
||||||
%{
|
%{
|
||||||
#ifdef max
|
#ifdef max
|
||||||
|
|
@ -23,20 +23,9 @@ namespace test {
|
||||||
char * blah(T x) {
|
char * blah(T x) {
|
||||||
return (char *) "vector::blah";
|
return (char *) "vector::blah";
|
||||||
}
|
}
|
||||||
|
void vectoruse(vector<T> a, test::vector<T> b) {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace test2 {
|
|
||||||
using namespace test;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace test3 {
|
|
||||||
using test::max;
|
|
||||||
using test::vector;
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace test2;
|
|
||||||
namespace T4 = test;
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
@ -48,6 +37,7 @@ namespace test {
|
||||||
char * blah(T x) {
|
char * blah(T x) {
|
||||||
return (char *) "vector::blah";
|
return (char *) "vector::blah";
|
||||||
}
|
}
|
||||||
|
void vectoruse(vector<T> a, test::vector<T> b) {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,30 +45,26 @@ using namespace test;
|
||||||
%template(maxint) max<int>;
|
%template(maxint) max<int>;
|
||||||
%template(vectorint) vector<int>;
|
%template(vectorint) vector<int>;
|
||||||
|
|
||||||
namespace test2 {
|
namespace test {
|
||||||
using namespace test;
|
|
||||||
%template(maxshort) max<short>;
|
%template(maxshort) max<short>;
|
||||||
%template(vectorshort) vector<short>;
|
%template(vectorshort) vector<short>;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace test3 {
|
namespace test {
|
||||||
using test::max;
|
|
||||||
using test::vector;
|
|
||||||
%template(maxlong) max<long>;
|
%template(maxlong) max<long>;
|
||||||
%template(vectorlong) vector<long>;
|
%template(vectorlong) vector<long>;
|
||||||
}
|
}
|
||||||
|
|
||||||
%inline %{
|
%inline %{
|
||||||
|
|
||||||
namespace test4 {
|
namespace test {
|
||||||
using namespace test;
|
typedef char Char;
|
||||||
typedef int Integer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
namespace test4 {
|
namespace test {
|
||||||
%template(maxInteger) max<Integer>;
|
%template(maxchar) max<Char>;
|
||||||
%template(vectorInteger) vector<Integer>;
|
%template(vectorchar) vector<Char>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import template_using_directive_typedef
|
||||||
|
|
||||||
|
vo = template_using_directive_typedef.Vector_Obj();
|
||||||
|
|
||||||
|
h = template_using_directive_typedef.Holder();
|
||||||
|
h.holder_use1(vo, vo, vo);
|
||||||
|
h.holder_use2(vo, vo, vo);
|
||||||
|
h.holder_use3(vo, vo, vo);
|
||||||
|
|
||||||
|
template_using_directive_typedef.tns_holder_use(vo, vo);
|
||||||
|
template_using_directive_typedef.tns_use(vo, vo, vo);
|
||||||
|
template_using_directive_typedef.global_holder_use(vo);
|
||||||
|
template_using_directive_typedef.global_use(vo, vo, vo);
|
||||||
|
template_using_directive_typedef.ns1_holder_use(vo);
|
||||||
|
template_using_directive_typedef.ns2_holder_use(vo, vo, vo, vo);
|
||||||
32
Examples/test-suite/python/typemap_template_typedef_runme.py
Normal file
32
Examples/test-suite/python/typemap_template_typedef_runme.py
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
from typemap_template_typedef import *
|
||||||
|
|
||||||
|
def check(got, expected):
|
||||||
|
if got != expected:
|
||||||
|
raise RuntimeError("got: " + str(got) + " expected: " + str(expected))
|
||||||
|
|
||||||
|
x = XXXInt()
|
||||||
|
|
||||||
|
check(x.aa1(0), 0)
|
||||||
|
check(x.aa2(0), 55)
|
||||||
|
check(x.aa3(0), 0)
|
||||||
|
check(aa1(0), 0)
|
||||||
|
check(aa2(0), 0)
|
||||||
|
|
||||||
|
check(x.bb1(0), 0)
|
||||||
|
check(x.bb2(0), 66)
|
||||||
|
check(x.bb3(0), 0)
|
||||||
|
check(bb1(0), 0)
|
||||||
|
check(bb2(0), 0)
|
||||||
|
|
||||||
|
check(x.cc1(0), 0)
|
||||||
|
check(x.cc2(0), 77)
|
||||||
|
check(x.cc3(0), 77)
|
||||||
|
check(cc1(0), 0)
|
||||||
|
check(cc2(0), 0)
|
||||||
|
|
||||||
|
check(x.dd1(0), 0)
|
||||||
|
check(x.dd2(0), 88)
|
||||||
|
check(x.dd3(0), 0)
|
||||||
|
check(dd1(0), 0)
|
||||||
|
check(dd2(0), 0)
|
||||||
|
|
||||||
|
|
@ -49,11 +49,6 @@ namespace one
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
%define PTR_DEF(o)
|
|
||||||
typedef one::Ptr<o> o ## _ptr;
|
|
||||||
%template(o ## _ptr) one::Ptr<o>;
|
|
||||||
%enddef
|
|
||||||
|
|
||||||
namespace one
|
namespace one
|
||||||
{
|
{
|
||||||
class Obj1
|
class Obj1
|
||||||
|
|
@ -63,7 +58,8 @@ namespace one
|
||||||
void donothing() {}
|
void donothing() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
PTR_DEF(Obj1)
|
typedef one::Ptr<Obj1> Obj1_ptr;
|
||||||
|
%template(Obj1_ptr) one::Ptr<Obj1>;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace two
|
namespace two
|
||||||
|
|
@ -75,6 +71,9 @@ namespace two
|
||||||
void donothing() {}
|
void donothing() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
PTR_DEF(Obj2)
|
typedef one::Ptr<Obj2> Obj2_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using two::Obj2;
|
||||||
|
%template(Obj2_ptr) one::Ptr<Obj2>;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,30 @@
|
||||||
#pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_TEMPLATE
|
|
||||||
|
|
||||||
%module template_nested_typemaps
|
%module template_nested_typemaps
|
||||||
|
|
||||||
// Testing that the typemaps invoked within a class via %template are picked up by appropriate methods
|
#pragma SWIG nowarn=SWIGWARN_PARSE_NAMED_NESTED_CLASS
|
||||||
|
|
||||||
template <typename T> struct Typemap {
|
// Testing that the typemaps invoked within a class via %template are picked up by appropriate methods
|
||||||
%typemap(in) T {
|
// Only for languages that support nested classes
|
||||||
$1 = -99;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <> struct Typemap<short> { // Note explicit specialization
|
|
||||||
%typemap(in) short {
|
|
||||||
$1 = -77;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
%inline %{
|
%inline %{
|
||||||
int globalInt1(int s) { return s; }
|
int globalInt1(int s) { return s; }
|
||||||
short globalShort1(short s) { return s; }
|
short globalShort1(short s) { return s; }
|
||||||
|
|
||||||
template <typename T> struct Breeze {
|
template <typename T> struct Breeze {
|
||||||
|
template <typename TMT> struct Typemap {
|
||||||
|
#ifdef SWIG
|
||||||
|
%typemap(in) TMT {
|
||||||
|
$1 = -99;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
template <typename TMT> struct TypemapShort {
|
||||||
|
#ifdef SWIG
|
||||||
|
%typemap(in) short {
|
||||||
|
$1 = -77;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
int methodInt1(int s) { return s; }
|
int methodInt1(int s) { return s; }
|
||||||
#if defined(SWIG)
|
#if defined(SWIG)
|
||||||
%template() Typemap<int>;
|
%template() Typemap<int>;
|
||||||
|
|
@ -29,7 +34,7 @@ template <typename T> struct Breeze {
|
||||||
|
|
||||||
short methodShort1(short s) { return s; }
|
short methodShort1(short s) { return s; }
|
||||||
#if defined(SWIG)
|
#if defined(SWIG)
|
||||||
%template(TypemapShort) Typemap<short>; // should issue warning SWIGWARN_PARSE_NESTED_TEMPLATE
|
%template() TypemapShort<short>;
|
||||||
#endif
|
#endif
|
||||||
short methodShort2(short s) { return s; } // should pick up the typemap within Typemap<short>
|
short methodShort2(short s) { return s; } // should pick up the typemap within Typemap<short>
|
||||||
};
|
};
|
||||||
|
|
|
||||||
133
Examples/test-suite/template_parameters_global_scope.i
Normal file
133
Examples/test-suite/template_parameters_global_scope.i
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
%module template_parameters_global_scope
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
namespace Alloc {
|
||||||
|
template<typename T> struct Rebind {
|
||||||
|
typedef int Integer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
struct Bucket_ {};
|
||||||
|
typedef Bucket_ TDBucket;
|
||||||
|
typedef ::Bucket_ TDGlobalBucket;
|
||||||
|
%}
|
||||||
|
|
||||||
|
// Check 1: %template no unary scope operator
|
||||||
|
%template(RebindBucket) Alloc::Rebind< Bucket_ >;
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
Alloc::Rebind< Bucket_ >::Integer Bucket1() { return 1; }
|
||||||
|
Alloc::Rebind< ::Bucket_ >::Integer Bucket2() { return 2; }
|
||||||
|
Alloc::Rebind< TDBucket >::Integer Bucket3() { return 3; }
|
||||||
|
Alloc::Rebind< ::TDBucket >::Integer Bucket4() { return 4; }
|
||||||
|
Alloc::Rebind< TDGlobalBucket >::Integer Bucket5() { return 5; }
|
||||||
|
Alloc::Rebind< ::TDGlobalBucket >::Integer Bucket6() { return 6; }
|
||||||
|
%}
|
||||||
|
|
||||||
|
// Check 2: %template with unary scope operator
|
||||||
|
%inline %{
|
||||||
|
struct Spade {};
|
||||||
|
typedef Spade TDSpade;
|
||||||
|
typedef ::Spade TDGlobalSpade;
|
||||||
|
%}
|
||||||
|
%template(RebindSpade) Alloc::Rebind< ::Spade >;
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
Alloc::Rebind< Spade >::Integer Spade1() { return 1; }
|
||||||
|
Alloc::Rebind< ::Spade >::Integer Spade2() { return 2; }
|
||||||
|
Alloc::Rebind< TDSpade >::Integer Spade3() { return 3; }
|
||||||
|
Alloc::Rebind< ::TDSpade >::Integer Spade4() { return 4; }
|
||||||
|
Alloc::Rebind< TDGlobalSpade >::Integer Spade5() { return 5; }
|
||||||
|
Alloc::Rebind< ::TDGlobalSpade >::Integer Spade6() { return 6; }
|
||||||
|
%}
|
||||||
|
|
||||||
|
// Check 3: %template typedef no unary scope operator
|
||||||
|
%inline %{
|
||||||
|
struct Ball {};
|
||||||
|
typedef Ball TDBall;
|
||||||
|
typedef ::Ball TDGlobalBall;
|
||||||
|
%}
|
||||||
|
%template(RebindBall) Alloc::Rebind< TDBall >;
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
Alloc::Rebind< Ball >::Integer Ball1() { return 1; }
|
||||||
|
Alloc::Rebind< ::Ball >::Integer Ball2() { return 2; }
|
||||||
|
Alloc::Rebind< TDBall >::Integer Ball3() { return 3; }
|
||||||
|
Alloc::Rebind< ::TDBall >::Integer Ball4() { return 4; }
|
||||||
|
Alloc::Rebind< TDGlobalBall >::Integer Ball5() { return 5; }
|
||||||
|
Alloc::Rebind< ::TDGlobalBall >::Integer Ball6() { return 6; }
|
||||||
|
%}
|
||||||
|
|
||||||
|
// Check 4: %template typedef with unary scope operator
|
||||||
|
%inline %{
|
||||||
|
struct Bat {};
|
||||||
|
typedef Bat TDBat;
|
||||||
|
typedef ::Bat TDGlobalBat;
|
||||||
|
%}
|
||||||
|
%template(RebindBat) Alloc::Rebind< ::TDBat >;
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
Alloc::Rebind< Bat >::Integer Bat1() { return 1; }
|
||||||
|
Alloc::Rebind< ::Bat >::Integer Bat2() { return 2; }
|
||||||
|
Alloc::Rebind< TDBat >::Integer Bat3() { return 3; }
|
||||||
|
Alloc::Rebind< ::TDBat >::Integer Bat4() { return 4; }
|
||||||
|
Alloc::Rebind< TDGlobalBat >::Integer Bat5() { return 5; }
|
||||||
|
Alloc::Rebind< ::TDGlobalBat >::Integer Bat6() { return 6; }
|
||||||
|
%}
|
||||||
|
|
||||||
|
// Check 5: %template double typedef no unary scope operator
|
||||||
|
%inline %{
|
||||||
|
struct Chair {};
|
||||||
|
typedef Chair TDChair;
|
||||||
|
typedef ::Chair TDGlobalChair;
|
||||||
|
%}
|
||||||
|
%template(RebindChair) Alloc::Rebind< TDGlobalChair >;
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
Alloc::Rebind< Chair >::Integer Chair1() { return 1; }
|
||||||
|
Alloc::Rebind< ::Chair >::Integer Chair2() { return 2; }
|
||||||
|
Alloc::Rebind< TDChair >::Integer Chair3() { return 3; }
|
||||||
|
Alloc::Rebind< ::TDChair >::Integer Chair4() { return 4; }
|
||||||
|
Alloc::Rebind< TDGlobalChair >::Integer Chair5() { return 5; }
|
||||||
|
Alloc::Rebind< ::TDGlobalChair >::Integer Chair6() { return 6; }
|
||||||
|
%}
|
||||||
|
|
||||||
|
// Check 6: %template double typedef with unary scope operator
|
||||||
|
%inline %{
|
||||||
|
struct Table {};
|
||||||
|
typedef Table TDTable;
|
||||||
|
typedef ::Table TDGlobalTable;
|
||||||
|
%}
|
||||||
|
%template(RebindTable) Alloc::Rebind< ::TDGlobalTable >;
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
Alloc::Rebind< Table >::Integer Table1() { return 1; }
|
||||||
|
Alloc::Rebind< ::Table >::Integer Table2() { return 2; }
|
||||||
|
Alloc::Rebind< TDTable >::Integer Table3() { return 3; }
|
||||||
|
Alloc::Rebind< ::TDTable >::Integer Table4() { return 4; }
|
||||||
|
Alloc::Rebind< TDGlobalTable >::Integer Table5() { return 5; }
|
||||||
|
Alloc::Rebind< ::TDGlobalTable >::Integer Table6() { return 6; }
|
||||||
|
%}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
%inline %{
|
||||||
|
namespace Alloc {
|
||||||
|
template<typename T=::Spade/*, typename T2=TDSpade, typename T3=::TDSpade, typename T4=TDGlobalSpade, typename T5=::TDGlobalSpade*/> struct Rejig {
|
||||||
|
typedef int Integer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
%template(RejigSpade) Alloc::Rejig<::Spade>;
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
Alloc::Rejig<>::Integer rejig1() { return 1; }
|
||||||
|
Alloc::Rejig< ::Spade >::Integer rejig2() { return 2; }
|
||||||
|
Alloc::Rejig< ::TDSpade >::Integer rejig3() { return 3; }
|
||||||
|
Alloc::Rejig< ::TDSpade >::Integer rejig4() { return 4; }
|
||||||
|
Alloc::Rejig< TDGlobalSpade >::Integer rejig5() { return 5; }
|
||||||
|
Alloc::Rejig< ::TDGlobalSpade >::Integer rejig6() { return 6; }
|
||||||
|
%}
|
||||||
|
#endif
|
||||||
|
|
@ -32,7 +32,7 @@ namespace One {
|
||||||
%template(H) One::OneParm<int **>;
|
%template(H) One::OneParm<int **>;
|
||||||
|
|
||||||
// %template scope explicit specializations
|
// %template scope explicit specializations
|
||||||
namespace ONE {
|
namespace One {
|
||||||
%template(I) One::OneParm<float>;
|
%template(I) One::OneParm<float>;
|
||||||
%template(J) ::One::OneParm<float *>;
|
%template(J) ::One::OneParm<float *>;
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +42,7 @@ namespace One {
|
||||||
}
|
}
|
||||||
|
|
||||||
// %template scope partial specializations
|
// %template scope partial specializations
|
||||||
namespace ONE {
|
namespace One {
|
||||||
%template(BB) One::OneParm<bool *>;
|
%template(BB) One::OneParm<bool *>;
|
||||||
%template(BBB) ::One::OneParm<char *>;
|
%template(BBB) ::One::OneParm<char *>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ namespace One {
|
||||||
%template(H) One::OneParm<TypeDef::IntPtrPtr>;
|
%template(H) One::OneParm<TypeDef::IntPtrPtr>;
|
||||||
|
|
||||||
// %template scope explicit specializations
|
// %template scope explicit specializations
|
||||||
namespace ONE {
|
namespace One {
|
||||||
%template(I) One::OneParm<TypeDef::Float>;
|
%template(I) One::OneParm<TypeDef::Float>;
|
||||||
%template(J) ::One::OneParm<TypeDef::FloatPtr>;
|
%template(J) ::One::OneParm<TypeDef::FloatPtr>;
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +69,7 @@ namespace One {
|
||||||
}
|
}
|
||||||
|
|
||||||
// %template scope partial specializations
|
// %template scope partial specializations
|
||||||
namespace ONE {
|
namespace One {
|
||||||
%template(BB) One::OneParm<TypeDef::BoolPtr>;
|
%template(BB) One::OneParm<TypeDef::BoolPtr>;
|
||||||
%template(BBB) ::One::OneParm<TypeDef::CharPtr>;
|
%template(BBB) ::One::OneParm<TypeDef::CharPtr>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
66
Examples/test-suite/typemap_template_typedef.i
Normal file
66
Examples/test-suite/typemap_template_typedef.i
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
%module typemap_template_typedef
|
||||||
|
//%module("templatereduce") typemap_template_typedef
|
||||||
|
|
||||||
|
%typemap(in) int TMAP55 %{ $1 = 55; /* int TMAP55 typemap */ %}
|
||||||
|
%typemap(in) int TMAP66 %{ $1 = 66; /* int TMAP66 typemap */ %}
|
||||||
|
%typemap(in) int TMAP77 %{ $1 = 77; /* int TMAP77 typemap */ %}
|
||||||
|
%typemap(in) int TMAP88 %{ $1 = 88; /* int TMAP88 typemap */ %}
|
||||||
|
|
||||||
|
%apply int TMAP77 { XXX<int>::Long cc }
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
typedef int Integer;
|
||||||
|
|
||||||
|
template<typename T> struct XXX {
|
||||||
|
#ifdef SWIG
|
||||||
|
// In swig-3.0.12 'Long aa' was actually stored as 'long aa' in typemap table instead of 'XXX<int>::Long aa'
|
||||||
|
%apply int TMAP55 { Long aa }
|
||||||
|
%apply int TMAP66 { XXX<int>::Long bb }
|
||||||
|
%apply int TMAP88 { XXX<Integer>::Long dd }
|
||||||
|
#endif
|
||||||
|
typedef long Long;
|
||||||
|
long aa1(long aa) { return aa; }
|
||||||
|
long aa2(Long aa) { return aa; }
|
||||||
|
long bb1(long bb) { return bb; }
|
||||||
|
long bb2(Long bb) { return bb; }
|
||||||
|
long cc1(long cc) { return cc; }
|
||||||
|
long cc2(Long cc) { return cc; }
|
||||||
|
long dd1(long dd) { return dd; }
|
||||||
|
long dd2(Long dd) { return dd; }
|
||||||
|
#ifdef SWIG
|
||||||
|
%clear Long aa;
|
||||||
|
%clear XXX<int>::Long bb;
|
||||||
|
%clear XXX<Integer>::Long dd;
|
||||||
|
#endif
|
||||||
|
long aa3(Long aa) { return aa; }
|
||||||
|
long bb3(Long bb) { return bb; }
|
||||||
|
long cc3(Long cc) { return cc; }
|
||||||
|
long dd3(Long dd) { return dd; }
|
||||||
|
};
|
||||||
|
%}
|
||||||
|
|
||||||
|
%template(XXXInt) XXX<Integer>;
|
||||||
|
|
||||||
|
%clear XXX<int>::Long cc;
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
long aa1(XXX<int>::Long aa) { return aa; }
|
||||||
|
long aa2(long aa) { return aa; }
|
||||||
|
long bb1(XXX<int>::Long bb) { return bb; }
|
||||||
|
long bb2(long bb) { return bb; }
|
||||||
|
long cc1(XXX<int>::Long cc) { return cc; }
|
||||||
|
long cc2(long cc) { return cc; }
|
||||||
|
long dd1(XXX<Integer>::Long dd) { return dd; }
|
||||||
|
long dd2(long dd) { return dd; }
|
||||||
|
%}
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
typedef Integer INTEGER;
|
||||||
|
template<typename T1, typename T2 = INTEGER> struct YYY {
|
||||||
|
void meff(T1 t1, T2 t2) {}
|
||||||
|
};
|
||||||
|
%}
|
||||||
|
%template(YYYIntInt) YYY<INTEGER>;
|
||||||
|
%inline %{
|
||||||
|
void whyohwhy(YYY<INTEGER> yy) {}
|
||||||
|
%}
|
||||||
|
|
@ -209,7 +209,7 @@ static String *yyrename = 0;
|
||||||
|
|
||||||
/* Forward renaming operator */
|
/* Forward renaming operator */
|
||||||
|
|
||||||
static String *resolve_create_node_scope(String *cname);
|
static String *resolve_create_node_scope(String *cname, int is_class_definition);
|
||||||
|
|
||||||
|
|
||||||
Hash *Swig_cparse_features(void) {
|
Hash *Swig_cparse_features(void) {
|
||||||
|
|
@ -815,32 +815,53 @@ static String *remove_block(Node *kw, const String *inputcode) {
|
||||||
return modified_code;
|
return modified_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define RESOLVE_DEBUG 1
|
||||||
|
*/
|
||||||
static Node *nscope = 0;
|
static Node *nscope = 0;
|
||||||
static Node *nscope_inner = 0;
|
static Node *nscope_inner = 0;
|
||||||
|
|
||||||
/* Remove the scope prefix from cname and return the base name without the prefix.
|
/* Remove the scope prefix from cname and return the base name without the prefix.
|
||||||
* The scopes required for the symbol name are resolved and/or created, if required.
|
* The scopes required for the symbol name are resolved and/or created, if required.
|
||||||
* For example AA::BB::CC as input returns CC and creates the namespace AA then inner
|
* For example AA::BB::CC as input returns CC and creates the namespace AA then inner
|
||||||
* namespace BB in the current scope. If cname is found to already exist as a weak symbol
|
* namespace BB in the current scope. */
|
||||||
* (forward reference) then the scope might be changed to match, such as when a symbol match
|
static String *resolve_create_node_scope(String *cname, int is_class_definition) {
|
||||||
* is made via a using reference. */
|
|
||||||
static String *resolve_create_node_scope(String *cname) {
|
|
||||||
Symtab *gscope = 0;
|
Symtab *gscope = 0;
|
||||||
Node *cname_node = 0;
|
Node *cname_node = 0;
|
||||||
int skip_lookup = 0;
|
String *last = Swig_scopename_last(cname);
|
||||||
nscope = 0;
|
nscope = 0;
|
||||||
nscope_inner = 0;
|
nscope_inner = 0;
|
||||||
|
|
||||||
if (Strncmp(cname,"::",2) == 0)
|
if (Strncmp(cname,"::" ,2) != 0) {
|
||||||
skip_lookup = 1;
|
if (is_class_definition) {
|
||||||
|
/* Only lookup symbols which are in scope via a using declaration but not via a using directive.
|
||||||
cname_node = skip_lookup ? 0 : Swig_symbol_clookup_no_inherit(cname, 0);
|
For example find y via 'using x::y' but not y via a 'using namespace x'. */
|
||||||
|
cname_node = Swig_symbol_clookup_no_inherit(cname, 0);
|
||||||
|
if (!cname_node) {
|
||||||
|
Node *full_lookup_node = Swig_symbol_clookup(cname, 0);
|
||||||
|
if (full_lookup_node) {
|
||||||
|
/* This finds a symbol brought into scope via both a using directive and a using declaration. */
|
||||||
|
Node *last_node = Swig_symbol_clookup_no_inherit(last, 0);
|
||||||
|
if (last_node == full_lookup_node)
|
||||||
|
cname_node = last_node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* For %template, the template needs to be in scope via any means. */
|
||||||
|
cname_node = Swig_symbol_clookup(cname, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if RESOLVE_DEBUG
|
||||||
|
if (!cname_node)
|
||||||
|
Printf(stdout, "symbol does not yet exist (%d): [%s]\n", is_class_definition, cname);
|
||||||
|
else
|
||||||
|
Printf(stdout, "symbol does exist (%d): [%s]\n", is_class_definition, cname);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (cname_node) {
|
if (cname_node) {
|
||||||
/* The symbol has been defined already or is in another scope.
|
/* The symbol has been defined already or is in another scope.
|
||||||
If it is a weak symbol, it needs replacing and if it was brought into the current scope
|
If it is a weak symbol, it needs replacing and if it was brought into the current scope,
|
||||||
via a using declaration, the scope needs adjusting appropriately for the new symbol.
|
the scope needs adjusting appropriately for the new symbol.
|
||||||
Similarly for defined templates. */
|
Similarly for defined templates. */
|
||||||
Symtab *symtab = Getattr(cname_node, "sym:symtab");
|
Symtab *symtab = Getattr(cname_node, "sym:symtab");
|
||||||
Node *sym_weak = Getattr(cname_node, "sym:weak");
|
Node *sym_weak = Getattr(cname_node, "sym:weak");
|
||||||
|
|
@ -848,48 +869,92 @@ static String *resolve_create_node_scope(String *cname) {
|
||||||
/* Check if the scope is the current scope */
|
/* Check if the scope is the current scope */
|
||||||
String *current_scopename = Swig_symbol_qualifiedscopename(0);
|
String *current_scopename = Swig_symbol_qualifiedscopename(0);
|
||||||
String *found_scopename = Swig_symbol_qualifiedscopename(symtab);
|
String *found_scopename = Swig_symbol_qualifiedscopename(symtab);
|
||||||
int len;
|
|
||||||
if (!current_scopename)
|
if (!current_scopename)
|
||||||
current_scopename = NewString("");
|
current_scopename = NewString("");
|
||||||
if (!found_scopename)
|
if (!found_scopename)
|
||||||
found_scopename = NewString("");
|
found_scopename = NewString("");
|
||||||
len = Len(current_scopename);
|
|
||||||
if ((len > 0) && (Strncmp(current_scopename, found_scopename, len) == 0)) {
|
{
|
||||||
if (Len(found_scopename) > len + 2) {
|
int fail = 1;
|
||||||
/* A matching weak symbol was found in non-global scope, some scope adjustment may be required */
|
List *current_scopes = Swig_scopename_tolist(current_scopename);
|
||||||
String *new_cname = NewString(Char(found_scopename) + len + 2); /* skip over "::" prefix */
|
List *found_scopes = Swig_scopename_tolist(found_scopename);
|
||||||
String *base = Swig_scopename_last(cname);
|
Iterator cit = First(current_scopes);
|
||||||
Printf(new_cname, "::%s", base);
|
Iterator fit = First(found_scopes);
|
||||||
cname = new_cname;
|
#if RESOLVE_DEBUG
|
||||||
Delete(base);
|
Printf(stdout, "comparing current: [%s] found: [%s]\n", current_scopename, found_scopename);
|
||||||
} else {
|
#endif
|
||||||
/* A matching weak symbol was found in the same non-global local scope, no scope adjustment required */
|
for (; fit.item && cit.item; fit = Next(fit), cit = Next(cit)) {
|
||||||
assert(len == Len(found_scopename));
|
String *current = cit.item;
|
||||||
|
String *found = fit.item;
|
||||||
|
#if RESOLVE_DEBUG
|
||||||
|
Printf(stdout, " looping %s %s\n", current, found);
|
||||||
|
#endif
|
||||||
|
if (Strcmp(current, found) != 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
String *base = Swig_scopename_last(cname);
|
if (!cit.item) {
|
||||||
if (Len(found_scopename) > 0) {
|
String *subscope = NewString("");
|
||||||
/* A matching weak symbol was found in a different scope to the local scope - probably via a using declaration */
|
for (; fit.item; fit = Next(fit)) {
|
||||||
cname = NewStringf("%s::%s", found_scopename, base);
|
if (Len(subscope) > 0)
|
||||||
} else {
|
Append(subscope, "::");
|
||||||
/* Either:
|
Append(subscope, fit.item);
|
||||||
1) A matching weak symbol was found in a different scope to the local scope - this is actually a
|
|
||||||
symbol with the same name in a different scope which we don't want, so no adjustment required.
|
|
||||||
2) A matching weak symbol was found in the global scope - no adjustment required.
|
|
||||||
*/
|
|
||||||
cname = Copy(base);
|
|
||||||
}
|
}
|
||||||
Delete(base);
|
if (Len(subscope) > 0)
|
||||||
|
cname = NewStringf("%s::%s", subscope, last);
|
||||||
|
else
|
||||||
|
cname = Copy(last);
|
||||||
|
#if RESOLVE_DEBUG
|
||||||
|
Printf(stdout, "subscope to create: [%s] cname: [%s]\n", subscope, cname);
|
||||||
|
#endif
|
||||||
|
fail = 0;
|
||||||
|
Delete(subscope);
|
||||||
|
} else {
|
||||||
|
if (is_class_definition) {
|
||||||
|
if (!fit.item) {
|
||||||
|
/* It is valid to define a new class with the same name as one forward declared in a parent scope */
|
||||||
|
fail = 0;
|
||||||
|
} else if (Swig_scopename_check(cname)) {
|
||||||
|
/* Classes defined with scope qualifiers must have a matching forward declaration in matching scope */
|
||||||
|
fail = 1;
|
||||||
|
} else {
|
||||||
|
/* This may let through some invalid cases */
|
||||||
|
fail = 0;
|
||||||
}
|
}
|
||||||
|
#if RESOLVE_DEBUG
|
||||||
|
Printf(stdout, "scope for class definition, fail: %d\n", fail);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#if RESOLVE_DEBUG
|
||||||
|
Printf(stdout, "no matching base scope for template\n");
|
||||||
|
#endif
|
||||||
|
fail = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Delete(found_scopes);
|
||||||
|
Delete(current_scopes);
|
||||||
|
|
||||||
|
if (fail) {
|
||||||
|
String *cname_resolved = NewStringf("%s::%s", found_scopename, last);
|
||||||
|
Swig_error(cparse_file, cparse_line, "'%s' resolves to '%s' and was incorrectly instantiated in scope '%s' instead of within scope '%s'.\n", cname, cname_resolved, current_scopename, found_scopename);
|
||||||
|
cname = Copy(last);
|
||||||
|
Delete(cname_resolved);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Delete(current_scopename);
|
Delete(current_scopename);
|
||||||
Delete(found_scopename);
|
Delete(found_scopename);
|
||||||
}
|
}
|
||||||
|
} else if (!is_class_definition) {
|
||||||
|
/* A template instantiation requires a template to be found in scope... fail here too?
|
||||||
|
Swig_error(cparse_file, cparse_line, "No template found to instantiate '%s' with %%template.\n", cname);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Swig_scopename_check(cname)) {
|
if (Swig_scopename_check(cname)) {
|
||||||
Node *ns;
|
Node *ns;
|
||||||
String *prefix = Swig_scopename_prefix(cname);
|
String *prefix = Swig_scopename_prefix(cname);
|
||||||
String *base = Swig_scopename_last(cname);
|
|
||||||
if (prefix && (Strncmp(prefix,"::",2) == 0)) {
|
if (prefix && (Strncmp(prefix,"::",2) == 0)) {
|
||||||
/* I don't think we can use :: global scope to declare classes and hence neither %template. - consider reporting error instead - wsfulton. */
|
/* I don't think we can use :: global scope to declare classes and hence neither %template. - consider reporting error instead - wsfulton. */
|
||||||
/* Use the global scope */
|
/* Use the global scope */
|
||||||
|
|
@ -899,6 +964,7 @@ static String *resolve_create_node_scope(String *cname) {
|
||||||
gscope = set_scope_to_global();
|
gscope = set_scope_to_global();
|
||||||
}
|
}
|
||||||
if (Len(prefix) == 0) {
|
if (Len(prefix) == 0) {
|
||||||
|
String *base = Copy(last);
|
||||||
/* Use the global scope, but we need to add a 'global' namespace. */
|
/* Use the global scope, but we need to add a 'global' namespace. */
|
||||||
if (!gscope) gscope = set_scope_to_global();
|
if (!gscope) gscope = set_scope_to_global();
|
||||||
/* note that this namespace is not the "unnamed" one,
|
/* note that this namespace is not the "unnamed" one,
|
||||||
|
|
@ -907,6 +973,7 @@ static String *resolve_create_node_scope(String *cname) {
|
||||||
nscope = new_node("namespace");
|
nscope = new_node("namespace");
|
||||||
Setattr(nscope,"symtab", gscope);;
|
Setattr(nscope,"symtab", gscope);;
|
||||||
nscope_inner = nscope;
|
nscope_inner = nscope;
|
||||||
|
Delete(last);
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
/* Try to locate the scope */
|
/* Try to locate the scope */
|
||||||
|
|
@ -924,7 +991,7 @@ static String *resolve_create_node_scope(String *cname) {
|
||||||
String *nname = Swig_symbol_qualifiedscopename(nstab);
|
String *nname = Swig_symbol_qualifiedscopename(nstab);
|
||||||
if (tname && (Strcmp(tname,nname) == 0)) {
|
if (tname && (Strcmp(tname,nname) == 0)) {
|
||||||
ns = 0;
|
ns = 0;
|
||||||
cname = base;
|
cname = Copy(last);
|
||||||
}
|
}
|
||||||
Delete(tname);
|
Delete(tname);
|
||||||
Delete(nname);
|
Delete(nname);
|
||||||
|
|
@ -932,19 +999,10 @@ static String *resolve_create_node_scope(String *cname) {
|
||||||
if (ns) {
|
if (ns) {
|
||||||
/* we will try to create a new node using the namespaces we
|
/* we will try to create a new node using the namespaces we
|
||||||
can find in the scope name */
|
can find in the scope name */
|
||||||
List *scopes;
|
List *scopes = Swig_scopename_tolist(prefix);
|
||||||
String *sname;
|
String *sname;
|
||||||
Iterator si;
|
Iterator si;
|
||||||
String *name = NewString(prefix);
|
|
||||||
scopes = NewList();
|
|
||||||
while (name) {
|
|
||||||
String *base = Swig_scopename_last(name);
|
|
||||||
String *tprefix = Swig_scopename_prefix(name);
|
|
||||||
Insert(scopes,0,base);
|
|
||||||
Delete(base);
|
|
||||||
Delete(name);
|
|
||||||
name = tprefix;
|
|
||||||
}
|
|
||||||
for (si = First(scopes); si.item; si = Next(si)) {
|
for (si = First(scopes); si.item; si = Next(si)) {
|
||||||
Node *ns1,*ns2;
|
Node *ns1,*ns2;
|
||||||
sname = si.item;
|
sname = si.item;
|
||||||
|
|
@ -990,12 +1048,13 @@ static String *resolve_create_node_scope(String *cname) {
|
||||||
nscope_inner = ns2;
|
nscope_inner = ns2;
|
||||||
if (!nscope) nscope = ns2;
|
if (!nscope) nscope = ns2;
|
||||||
}
|
}
|
||||||
cname = base;
|
cname = Copy(last);
|
||||||
Delete(scopes);
|
Delete(scopes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Delete(prefix);
|
Delete(prefix);
|
||||||
}
|
}
|
||||||
|
Delete(last);
|
||||||
|
|
||||||
return cname;
|
return cname;
|
||||||
}
|
}
|
||||||
|
|
@ -2631,9 +2690,8 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
|
||||||
tscope = Swig_symbol_current(); /* Get the current scope */
|
tscope = Swig_symbol_current(); /* Get the current scope */
|
||||||
|
|
||||||
/* If the class name is qualified, we need to create or lookup namespace entries */
|
/* If the class name is qualified, we need to create or lookup namespace entries */
|
||||||
if (!inclass) {
|
$5 = resolve_create_node_scope($5, 0);
|
||||||
$5 = resolve_create_node_scope($5);
|
|
||||||
}
|
|
||||||
if (nscope_inner && Strcmp(nodeType(nscope_inner), "class") == 0) {
|
if (nscope_inner && Strcmp(nodeType(nscope_inner), "class") == 0) {
|
||||||
outer_class = nscope_inner;
|
outer_class = nscope_inner;
|
||||||
}
|
}
|
||||||
|
|
@ -3523,7 +3581,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
|
||||||
Setattr($<node>$,"prev_symtab",Swig_symbol_current());
|
Setattr($<node>$,"prev_symtab",Swig_symbol_current());
|
||||||
|
|
||||||
/* If the class name is qualified. We need to create or lookup namespace/scope entries */
|
/* If the class name is qualified. We need to create or lookup namespace/scope entries */
|
||||||
scope = resolve_create_node_scope($3);
|
scope = resolve_create_node_scope($3, 1);
|
||||||
/* save nscope_inner to the class - it may be overwritten in nested classes*/
|
/* save nscope_inner to the class - it may be overwritten in nested classes*/
|
||||||
Setattr($<node>$, "nested:innerscope", nscope_inner);
|
Setattr($<node>$, "nested:innerscope", nscope_inner);
|
||||||
Setattr($<node>$, "nested:nscope", nscope);
|
Setattr($<node>$, "nested:nscope", nscope);
|
||||||
|
|
|
||||||
|
|
@ -1203,10 +1203,7 @@ class TypePass:private Dispatcher {
|
||||||
} else if (Strcmp(ntype, "enum") == 0) {
|
} else if (Strcmp(ntype, "enum") == 0) {
|
||||||
SwigType_typedef_using(Getattr(n, "uname"));
|
SwigType_typedef_using(Getattr(n, "uname"));
|
||||||
} else if (Strcmp(ntype, "template") == 0) {
|
} else if (Strcmp(ntype, "template") == 0) {
|
||||||
/*
|
|
||||||
Printf(stdout, "usingDeclaration template %s --- %s\n", Getattr(n, "name"), Getattr(n, "uname"));
|
|
||||||
SwigType_typedef_using(Getattr(n, "uname"));
|
SwigType_typedef_using(Getattr(n, "uname"));
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -823,10 +823,11 @@ String *Swig_string_emangle(String *s) {
|
||||||
|
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* Swig_scopename_prefix()
|
* Swig_scopename_split()
|
||||||
*
|
*
|
||||||
* Take a qualified name like "A::B::C" and return the scope name.
|
* Take a qualified name like "A::B::C" and splits off the last name.
|
||||||
* In this case, "A::B". Returns NULL if there is no base.
|
* In this case, returns "C" as last and "A::B" as prefix.
|
||||||
|
* Always returns non NULL for last, but prefix may be NULL if there is no prefix.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void Swig_scopename_split(const String *s, String **rprefix, String **rlast) {
|
void Swig_scopename_split(const String *s, String **rprefix, String **rlast) {
|
||||||
|
|
@ -882,6 +883,12 @@ void Swig_scopename_split(const String *s, String **rprefix, String **rlast) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* Swig_scopename_prefix()
|
||||||
|
*
|
||||||
|
* Take a qualified name like "A::B::C" and return the scope name.
|
||||||
|
* In this case, "A::B". Returns NULL if there is no base.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
String *Swig_scopename_prefix(const String *s) {
|
String *Swig_scopename_prefix(const String *s) {
|
||||||
char *tmp = Char(s);
|
char *tmp = Char(s);
|
||||||
|
|
@ -1067,6 +1074,31 @@ String *Swig_scopename_suffix(const String *s) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* Swig_scopename_tolist()
|
||||||
|
*
|
||||||
|
* Take a qualified scope name like "A::B::C" and convert it to a list.
|
||||||
|
* In this case, return a list of 3 elements "A", "B", "C".
|
||||||
|
* Returns an empty list if the input is empty.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
List *Swig_scopename_tolist(const String *s) {
|
||||||
|
List *scopes = NewList();
|
||||||
|
String *name = Len(s) == 0 ? 0 : NewString(s);
|
||||||
|
|
||||||
|
while (name) {
|
||||||
|
String *last = 0;
|
||||||
|
String *prefix = 0;
|
||||||
|
Swig_scopename_split(name, &prefix, &last);
|
||||||
|
Insert(scopes, 0, last);
|
||||||
|
Delete(last);
|
||||||
|
Delete(name);
|
||||||
|
name = prefix;
|
||||||
|
}
|
||||||
|
Delete(name);
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* Swig_scopename_check()
|
* Swig_scopename_check()
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -326,6 +326,7 @@ extern int ParmList_is_compactdefargs(ParmList *p);
|
||||||
extern String *Swig_scopename_last(const String *s);
|
extern String *Swig_scopename_last(const String *s);
|
||||||
extern String *Swig_scopename_first(const String *s);
|
extern String *Swig_scopename_first(const String *s);
|
||||||
extern String *Swig_scopename_suffix(const String *s);
|
extern String *Swig_scopename_suffix(const String *s);
|
||||||
|
extern List *Swig_scopename_tolist(const String *s);
|
||||||
extern int Swig_scopename_check(const String *s);
|
extern int Swig_scopename_check(const String *s);
|
||||||
extern String *Swig_string_lower(String *s);
|
extern String *Swig_string_lower(String *s);
|
||||||
extern String *Swig_string_upper(String *s);
|
extern String *Swig_string_upper(String *s);
|
||||||
|
|
|
||||||
|
|
@ -61,13 +61,44 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper
|
||||||
|
|
||||||
static Hash *typemaps;
|
static Hash *typemaps;
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* typemap_identifier_fix()
|
||||||
|
*
|
||||||
|
* Create a type that can be used as a hash key lookup independent of the various
|
||||||
|
* ways a template parameter list can be defined. This is achieved by fully
|
||||||
|
* resolving the template parameters.
|
||||||
|
*
|
||||||
|
* This is a copy and modification of feature_identifier_fix in parser.y.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static SwigType *typemap_identifier_fix(const SwigType *s) {
|
||||||
|
String *tp = SwigType_istemplate_templateprefix(s);
|
||||||
|
if (tp) {
|
||||||
|
String *ts, *ta, *tq, *tr;
|
||||||
|
ts = SwigType_templatesuffix(s);
|
||||||
|
ta = SwigType_templateargs(s);
|
||||||
|
tq = Swig_symbol_type_qualify(ta, 0);
|
||||||
|
tr = SwigType_typedef_resolve_all(ta);
|
||||||
|
Append(tp,tr);
|
||||||
|
Append(tp,ts);
|
||||||
|
Delete(ts);
|
||||||
|
Delete(ta);
|
||||||
|
Delete(tq);
|
||||||
|
Delete(tr);
|
||||||
|
return tp;
|
||||||
|
} else {
|
||||||
|
return NewString(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static Hash *get_typemap(const SwigType *type) {
|
static Hash *get_typemap(const SwigType *type) {
|
||||||
Hash *tm = 0;
|
Hash *tm = 0;
|
||||||
SwigType *dtype = 0;
|
SwigType *dtype = 0;
|
||||||
SwigType *hashtype;
|
SwigType *hashtype;
|
||||||
|
|
||||||
if (SwigType_istemplate(type)) {
|
if (SwigType_istemplate(type)) {
|
||||||
String *ty = Swig_symbol_template_deftype(type, 0);
|
SwigType *rty = typemap_identifier_fix(type);
|
||||||
|
String *ty = Swig_symbol_template_deftype(rty, 0);
|
||||||
dtype = Swig_symbol_type_qualify(ty, 0);
|
dtype = Swig_symbol_type_qualify(ty, 0);
|
||||||
type = dtype;
|
type = dtype;
|
||||||
Delete(ty);
|
Delete(ty);
|
||||||
|
|
@ -88,7 +119,7 @@ static void set_typemap(const SwigType *type, Hash **tmhash) {
|
||||||
Hash *new_tm = 0;
|
Hash *new_tm = 0;
|
||||||
assert(*tmhash == 0);
|
assert(*tmhash == 0);
|
||||||
if (SwigType_istemplate(type)) {
|
if (SwigType_istemplate(type)) {
|
||||||
SwigType *rty = SwigType_typedef_resolve_all(type);
|
SwigType *rty = typemap_identifier_fix(type);
|
||||||
String *ty = Swig_symbol_template_deftype(rty, 0);
|
String *ty = Swig_symbol_template_deftype(rty, 0);
|
||||||
String *tyq = Swig_symbol_type_qualify(ty, 0);
|
String *tyq = Swig_symbol_type_qualify(ty, 0);
|
||||||
hashtype = SwigType_remove_global_scope_prefix(tyq);
|
hashtype = SwigType_remove_global_scope_prefix(tyq);
|
||||||
|
|
@ -733,6 +764,7 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type
|
||||||
SwigType *oldctype = ctype;
|
SwigType *oldctype = ctype;
|
||||||
ctype = SwigType_typedef_resolve(ctype_unstripped);
|
ctype = SwigType_typedef_resolve(ctype_unstripped);
|
||||||
Delete(oldctype);
|
Delete(oldctype);
|
||||||
|
Delete(ctype_unstripped);
|
||||||
ctype_unstripped = Copy(ctype);
|
ctype_unstripped = Copy(ctype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,15 @@
|
||||||
* "name" - Scope name
|
* "name" - Scope name
|
||||||
* "qname" - Fully qualified typename
|
* "qname" - Fully qualified typename
|
||||||
* "typetab" - Type table containing typenames and typedef information
|
* "typetab" - Type table containing typenames and typedef information
|
||||||
|
* For a given key in the typetab table, the value is a fully
|
||||||
|
* qualified name if not pointing to itself.
|
||||||
* "symtab" - Hash table of symbols defined in a scope
|
* "symtab" - Hash table of symbols defined in a scope
|
||||||
* "inherit" - List of inherited scopes
|
* "inherit" - List of inherited scopes
|
||||||
* "parent" - Parent scope
|
* "parent" - Parent scope
|
||||||
*
|
*
|
||||||
|
* The contents of these tables can be viewed for debugging using the -debug-typedef
|
||||||
|
* option which calls SwigType_print_scope().
|
||||||
|
*
|
||||||
* Typedef information is stored in the "typetab" hash table. For example,
|
* Typedef information is stored in the "typetab" hash table. For example,
|
||||||
* if you have these declarations:
|
* if you have these declarations:
|
||||||
*
|
*
|
||||||
|
|
@ -53,8 +58,7 @@
|
||||||
* typedef A B;
|
* typedef A B;
|
||||||
* typedef B *C;
|
* typedef B *C;
|
||||||
*
|
*
|
||||||
* typetab is built as follows:
|
* typetab in scope '' contains:
|
||||||
*
|
|
||||||
* "A" : "int"
|
* "A" : "int"
|
||||||
* "B" : "A"
|
* "B" : "A"
|
||||||
* "C" : "p.B"
|
* "C" : "p.B"
|
||||||
|
|
@ -67,6 +71,26 @@
|
||||||
* ---> a(40).p.p.A (B --> A)
|
* ---> a(40).p.p.A (B --> A)
|
||||||
* ---> a(40).p.p.int (A --> int)
|
* ---> a(40).p.p.int (A --> int)
|
||||||
*
|
*
|
||||||
|
*
|
||||||
|
* Using declarations are stored in the "typetab" hash table. For example,
|
||||||
|
*
|
||||||
|
* namespace NN {
|
||||||
|
* struct SS {};
|
||||||
|
* }
|
||||||
|
* namespace N {
|
||||||
|
* struct S {};
|
||||||
|
* using NN::SS;
|
||||||
|
* }
|
||||||
|
* using N::S;
|
||||||
|
*
|
||||||
|
* typetab in scope '' contains:
|
||||||
|
* "S" : "N::S"
|
||||||
|
*
|
||||||
|
* and typetab in scope 'N' contains:
|
||||||
|
* "SS" : "NN::SS"
|
||||||
|
* "S" : "S"
|
||||||
|
*
|
||||||
|
*
|
||||||
* For inheritance, SWIG tries to resolve types back to the base class. For instance, if
|
* For inheritance, SWIG tries to resolve types back to the base class. For instance, if
|
||||||
* you have this:
|
* you have this:
|
||||||
*
|
*
|
||||||
|
|
@ -74,13 +98,38 @@
|
||||||
* public:
|
* public:
|
||||||
* typedef int Integer;
|
* typedef int Integer;
|
||||||
* };
|
* };
|
||||||
*
|
* struct Bar : public Foo {
|
||||||
* class Bar : public Foo {
|
|
||||||
* void blah(Integer x);
|
* void blah(Integer x);
|
||||||
* };
|
* };
|
||||||
*
|
*
|
||||||
|
* In this case typetab in scope '' contains:
|
||||||
|
* "Foo" : "Foo"
|
||||||
|
* "Bar" : "Bar"
|
||||||
|
* and scope 'Foo' contains:
|
||||||
|
* "Integer" : "int"
|
||||||
|
* and scope 'Bar' inherits from 'Foo' but is empty (observe that blah is not a scope or typedef)
|
||||||
|
*
|
||||||
* The argument type of Bar::blah will be set to Foo::Integer.
|
* The argument type of Bar::blah will be set to Foo::Integer.
|
||||||
*
|
*
|
||||||
|
*
|
||||||
|
* The scope-inheritance mechanism is used to manage C++ using directives.
|
||||||
|
*
|
||||||
|
* namespace XX {
|
||||||
|
* class CC {};
|
||||||
|
* }
|
||||||
|
* namespace X {
|
||||||
|
* class C {};
|
||||||
|
* using namespace XX;
|
||||||
|
* }
|
||||||
|
* using namespace X;
|
||||||
|
*
|
||||||
|
* typetab in scope '' inherits from 'X'
|
||||||
|
* typetab in scope 'X' inherits from 'XX' and contains:
|
||||||
|
* "C" : "C"
|
||||||
|
* typetab in scope 'XX' contains:
|
||||||
|
* "CC" : "CC"
|
||||||
|
*
|
||||||
|
*
|
||||||
* The scope-inheritance mechanism is used to manage C++ namespace aliases.
|
* The scope-inheritance mechanism is used to manage C++ namespace aliases.
|
||||||
* For example, if you have this:
|
* For example, if you have this:
|
||||||
*
|
*
|
||||||
|
|
@ -90,8 +139,8 @@
|
||||||
*
|
*
|
||||||
* namespace F = Foo;
|
* namespace F = Foo;
|
||||||
*
|
*
|
||||||
* In this case, "F::" is defined as a scope that "inherits" from Foo. Internally,
|
* In this case, F is defined as a scope that "inherits" from Foo. Internally,
|
||||||
* "F::" will merely be an empty scope that refers to Foo. SWIG will never
|
* F will merely be an empty scope that points to Foo. SWIG will never
|
||||||
* place new type information into a namespace alias---attempts to do so
|
* place new type information into a namespace alias---attempts to do so
|
||||||
* will generate a warning message (in the parser) and will place information into
|
* will generate a warning message (in the parser) and will place information into
|
||||||
* Foo instead.
|
* Foo instead.
|
||||||
|
|
@ -166,6 +215,7 @@ void SwigType_typesystem_init() {
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name) {
|
int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name) {
|
||||||
|
/* Printf(stdout, "typedef %s %s\n", type, name); */
|
||||||
if (Getattr(current_typetab, name))
|
if (Getattr(current_typetab, name))
|
||||||
return -1; /* Already defined */
|
return -1; /* Already defined */
|
||||||
if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */
|
if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */
|
||||||
|
|
@ -248,10 +298,26 @@ void SwigType_new_scope(const_String_or_char_ptr name) {
|
||||||
ttab = NewHash();
|
ttab = NewHash();
|
||||||
Setattr(s, "typetab", ttab);
|
Setattr(s, "typetab", ttab);
|
||||||
|
|
||||||
/* Build fully qualified name and */
|
/* Build fully qualified name */
|
||||||
qname = SwigType_scope_name(s);
|
qname = SwigType_scope_name(s);
|
||||||
|
#if 1
|
||||||
|
{
|
||||||
|
/* TODO: only do with templates? What happens with non-templates with code below? */
|
||||||
|
String *stripped_qname;
|
||||||
|
stripped_qname = SwigType_remove_global_scope_prefix(qname);
|
||||||
|
/* Use fully qualified name for hash key without unary scope prefix, qname may contain unary scope */
|
||||||
|
Setattr(scopes, stripped_qname, s);
|
||||||
|
Setattr(s, "qname", qname);
|
||||||
|
/*
|
||||||
|
Printf(stdout, "SwigType_new_scope stripped %s %s\n", qname, stripped_qname);
|
||||||
|
*/
|
||||||
|
Delete(stripped_qname);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
Printf(stdout, "SwigType_new_scope %s\n", qname);
|
||||||
Setattr(scopes, qname, s);
|
Setattr(scopes, qname, s);
|
||||||
Setattr(s, "qname", qname);
|
Setattr(s, "qname", qname);
|
||||||
|
#endif
|
||||||
Delete(qname);
|
Delete(qname);
|
||||||
|
|
||||||
current_scope = s;
|
current_scope = s;
|
||||||
|
|
@ -418,12 +484,14 @@ static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) {
|
||||||
Typetab *s_orig = s;
|
Typetab *s_orig = s;
|
||||||
String *nnameprefix = 0;
|
String *nnameprefix = 0;
|
||||||
static int check_parent = 1;
|
static int check_parent = 1;
|
||||||
|
int is_template = 0;
|
||||||
|
|
||||||
if (Getmark(s))
|
if (Getmark(s))
|
||||||
return 0;
|
return 0;
|
||||||
Setmark(s, 1);
|
Setmark(s, 1);
|
||||||
|
|
||||||
if (SwigType_istemplate(nameprefix)) {
|
is_template = SwigType_istemplate(nameprefix);
|
||||||
|
if (is_template) {
|
||||||
nnameprefix = SwigType_typedef_resolve_all(nameprefix);
|
nnameprefix = SwigType_typedef_resolve_all(nameprefix);
|
||||||
nameprefix = nnameprefix;
|
nameprefix = nnameprefix;
|
||||||
}
|
}
|
||||||
|
|
@ -437,10 +505,12 @@ static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) {
|
||||||
} else {
|
} else {
|
||||||
full = NewString(nameprefix);
|
full = NewString(nameprefix);
|
||||||
}
|
}
|
||||||
if (Getattr(scopes, full)) {
|
|
||||||
s = Getattr(scopes, full);
|
s = Getattr(scopes, full);
|
||||||
} else {
|
if (!s && is_template) {
|
||||||
s = 0;
|
/* try look up scope with all the unary scope operators within the template parameter list removed */
|
||||||
|
SwigType *full_stripped = SwigType_remove_global_scope_prefix(full);
|
||||||
|
s = Getattr(scopes, full_stripped);
|
||||||
|
Delete(full_stripped);
|
||||||
}
|
}
|
||||||
Delete(full);
|
Delete(full);
|
||||||
if (s) {
|
if (s) {
|
||||||
|
|
@ -541,8 +611,11 @@ static SwigType *_typedef_resolve(Typetab *s, String *base, int look_parent) {
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* template_parameters_resolve()
|
* template_parameters_resolve()
|
||||||
*
|
*
|
||||||
* For use with templates only. The template parameters are resolved. If none
|
* For use with templates only. Attempts to resolve one template parameter.
|
||||||
* of the parameters can be resolved, zero is returned.
|
*
|
||||||
|
* If one of the template parameters can be resolved, the type is returned with
|
||||||
|
* just the one parameter resolved and the remaining parameters left as is.
|
||||||
|
* If none of the template parameters can be resolved, zero is returned.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static String *template_parameters_resolve(const String *base) {
|
static String *template_parameters_resolve(const String *base) {
|
||||||
|
|
@ -574,14 +647,15 @@ static String *template_parameters_resolve(const String *base) {
|
||||||
if ((i + 1) < sz)
|
if ((i + 1) < sz)
|
||||||
Append(type, ",");
|
Append(type, ",");
|
||||||
}
|
}
|
||||||
|
if (rep) {
|
||||||
Append(type, ")>");
|
Append(type, ")>");
|
||||||
Append(type, suffix);
|
Append(type, suffix);
|
||||||
Delete(suffix);
|
} else {
|
||||||
Delete(tparms);
|
|
||||||
if (!rep) {
|
|
||||||
Delete(type);
|
Delete(type);
|
||||||
type = 0;
|
type = 0;
|
||||||
}
|
}
|
||||||
|
Delete(suffix);
|
||||||
|
Delete(tparms);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -592,6 +666,17 @@ static SwigType *typedef_resolve(Typetab *s, String *base) {
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* SwigType_typedef_resolve()
|
* SwigType_typedef_resolve()
|
||||||
|
*
|
||||||
|
* Given a type declaration, this function looks to reduce/resolve the type via a
|
||||||
|
* typedef (including via C++ using declarations).
|
||||||
|
*
|
||||||
|
* If it is able to find a typedef, the resolved type is returned. If no typedef
|
||||||
|
* is found NULL is returned. The type name is resolved in the current scope.
|
||||||
|
* The type returned is not always fully qualified for the global scope, it is
|
||||||
|
* valid for use in the current scope. If the current scope is global scope, a
|
||||||
|
* fully qualified type should be returned.
|
||||||
|
*
|
||||||
|
* Some additional notes are in Doc/Manual/Extending.html.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* #define SWIG_DEBUG */
|
/* #define SWIG_DEBUG */
|
||||||
|
|
@ -718,6 +803,25 @@ SwigType *SwigType_typedef_resolve(const SwigType *t) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!type && SwigType_istemplate(base)) {
|
||||||
|
String *tprefix = SwigType_templateprefix(base);
|
||||||
|
String *rtprefix = SwigType_typedef_resolve(tprefix);
|
||||||
|
/* We're looking for a using declaration on the template prefix to resolve the template prefix
|
||||||
|
* in another scope. Using declaration do not have template parameters. */
|
||||||
|
if (rtprefix && !SwigType_istemplate(rtprefix)) {
|
||||||
|
String *tsuffix = SwigType_templatesuffix(base);
|
||||||
|
String *targs = SwigType_templateargs(base);
|
||||||
|
type = NewString(rtprefix);
|
||||||
|
newtype = 1;
|
||||||
|
Append(type, targs);
|
||||||
|
Append(type, tsuffix);
|
||||||
|
Delete(targs);
|
||||||
|
Delete(tsuffix);
|
||||||
|
Delete(rtprefix);
|
||||||
|
}
|
||||||
|
Delete(tprefix);
|
||||||
|
}
|
||||||
|
|
||||||
if (type && (Equal(base, type))) {
|
if (type && (Equal(base, type))) {
|
||||||
if (newtype)
|
if (newtype)
|
||||||
Delete(type);
|
Delete(type);
|
||||||
|
|
@ -911,6 +1015,9 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
|
||||||
return Copy(r);
|
return Copy(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SWIG_DEBUG
|
||||||
|
Printf(stdout, "SwigType_typedef_resolve_all start ... %s\n", t);
|
||||||
|
#endif
|
||||||
/* Recursively resolve the typedef */
|
/* Recursively resolve the typedef */
|
||||||
r = NewString(t);
|
r = NewString(t);
|
||||||
while ((n = SwigType_typedef_resolve(r))) {
|
while ((n = SwigType_typedef_resolve(r))) {
|
||||||
|
|
@ -931,6 +1038,9 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
|
||||||
Delete(key);
|
Delete(key);
|
||||||
Delete(rr);
|
Delete(rr);
|
||||||
}
|
}
|
||||||
|
#ifdef SWIG_DEBUG
|
||||||
|
Printf(stdout, "SwigType_typedef_resolve_all end === %s => %s\n", t, r);
|
||||||
|
#endif
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -938,8 +1048,17 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* SwigType_typedef_qualified()
|
* SwigType_typedef_qualified()
|
||||||
*
|
*
|
||||||
* Given a type declaration, this function tries to fully qualify it according to
|
* Given a type declaration, this function tries to fully qualify it so that the
|
||||||
* typedef scope rules.
|
* resulting type can be used in the global scope. The type name is resolved in
|
||||||
|
* the current scope.
|
||||||
|
*
|
||||||
|
* It provides a fully qualified name, not necessarily a fully expanded name.
|
||||||
|
* When a using declaration or using directive is found the type may not be fully
|
||||||
|
* expanded, but it will be resolved and fully qualified for use in the global scope.
|
||||||
|
*
|
||||||
|
* This function is for looking up scopes to qualify a type. It does not resolve
|
||||||
|
* C typedefs, it just qualifies them. See SwigType_typedef_resolve for resolving.
|
||||||
|
*
|
||||||
* If the unary scope operator (::) is used as a prefix to the type to denote global
|
* If the unary scope operator (::) is used as a prefix to the type to denote global
|
||||||
* scope, it is left in place.
|
* scope, it is left in place.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
@ -1000,20 +1119,14 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) {
|
||||||
out of the current scope */
|
out of the current scope */
|
||||||
|
|
||||||
Typetab *cs = current_scope;
|
Typetab *cs = current_scope;
|
||||||
while (cs) {
|
if (cs) {
|
||||||
String *qs = SwigType_scope_name(cs);
|
Typetab *found_scope = SwigType_find_scope(cs, e);
|
||||||
if (Len(qs)) {
|
if (found_scope) {
|
||||||
Append(qs, "::");
|
String *qs = SwigType_scope_name(found_scope);
|
||||||
}
|
|
||||||
Append(qs, e);
|
|
||||||
if (Getattr(scopes, qs)) {
|
|
||||||
Clear(e);
|
Clear(e);
|
||||||
Append(e, qs);
|
Append(e, qs);
|
||||||
Delete(qs);
|
Delete(qs);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
Delete(qs);
|
|
||||||
cs = Getattr(cs, "parent");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1029,10 +1142,6 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) {
|
||||||
Parm *p;
|
Parm *p;
|
||||||
List *parms;
|
List *parms;
|
||||||
ty = Swig_symbol_template_deftype(e, current_symtab);
|
ty = Swig_symbol_template_deftype(e, current_symtab);
|
||||||
/*
|
|
||||||
String *dt = Swig_symbol_template_deftype(e, current_symtab);
|
|
||||||
ty = Swig_symbol_type_qualify(dt, 0);
|
|
||||||
*/
|
|
||||||
e = ty;
|
e = ty;
|
||||||
parms = SwigType_parmlist(e);
|
parms = SwigType_parmlist(e);
|
||||||
tprefix = SwigType_templateprefix(e);
|
tprefix = SwigType_templateprefix(e);
|
||||||
|
|
@ -1099,9 +1208,6 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) {
|
||||||
Delete(tprefix);
|
Delete(tprefix);
|
||||||
Delete(qprefix);
|
Delete(qprefix);
|
||||||
Delete(parms);
|
Delete(parms);
|
||||||
/*
|
|
||||||
Delete(dt);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
Append(result, e);
|
Append(result, e);
|
||||||
Delete(ty);
|
Delete(ty);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue