%template scope enforcement and class definition fixes
The scoping rules around %template have been specified and enforced.
The %template directive for a class template is the equivalent to an
explicit instantiation of a C++ class template. The scope for a valid
%template instantiation is now 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.
For example, a few %template and explicit instantiations of std::vector
are shown below:
// valid
namespace std {
%template(vin) vector<int>;
template class vector<int>;
}
// valid
using namespace std;
%template(vin) vector<int>;
template class vector<int>;
// valid
using std::vector;
%template(vin) vector<int>;
template class vector<int>;
// ill-formed
namespace unrelated {
using std::vector;
%template(vin) vector<int>;
template class vector<int>;
}
// ill-formed
namespace unrelated {
using namespace std;
%template(vin) vector<int>;
template class vector<int>;
}
// ill-formed
namespace unrelated {
namespace std {
%template(vin) vector<int>;
template class vector<int>;
}
}
// ill-formed
namespace unrelated {
%template(vin) std::vector<int>;
template class std::vector<int>;
}
When the scope is incorrect, an error now occurs such as:
cpp_template_scope.i:34: Error: 'vector' resolves to 'std::vector' and
was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
Previously SWIG accepted the ill-formed examples above but this led to
numerous subtle template scope problems especially in the presence of
using declarations and using directives as well as with %feature and %typemap.
Actually, 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.
// valid C++03, ill-formed C++11
using std::vector;
template class vector<int>;
Similar fixes for defining classes using forward class references have
also been put in place. For example:
namespace Space1 {
struct A;
}
namespace Space2 {
struct Space1::A {
void x();
}
}
will now error out with:
cpp_class_definition.i:5: Error: 'Space1::A' resolves to 'Space1::A' and
was incorrectly instantiated in scope 'Space2' instead of within scope 'Space1'.
This commit is contained in:
parent
97ae9d66bc
commit
959e627208
21 changed files with 689 additions and 114 deletions
|
|
@ -56,6 +56,7 @@
|
|||
<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>
|
||||
|
|
@ -3599,7 +3600,108 @@ constructor, that will dispatch the proper call depending on the argument
|
|||
type.
|
||||
</p>
|
||||
|
||||
<H3><a name="SWIGPlus_template_more">6.18.7 More on templates</a></H3>
|
||||
<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>
|
||||
|
|
@ -4348,9 +4450,9 @@ In the example below, the generic template type is used to rename to <tt>bbb</tt
|
|||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%rename(bbb) Space::ABC::aaa(T t); // will match but with lower precedence than ccc
|
||||
%rename(bbb) Space::ABC::aaa(T t); // will match but with lower precedence than ccc
|
||||
%rename(ccc) Space::ABC<Space::XYZ>::aaa(Space::XYZ t);// will match but with higher precedence
|
||||
// than bbb
|
||||
// than bbb
|
||||
|
||||
namespace Space {
|
||||
class XYZ {};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue