Although I try to avoid anything other than the most primitive c++ templates, I occasionally have to use the following construct:
template <typename float_type, template <typename float_type> class c2_class > class c2_typed_ptr : public c2_const_ptr<float_type>
{
...
}
which causes swig to report a syntax error. Because I am not a particular template wizard, it took a while before I verified that this was legal c++ (by reading the BNF description for c++ in detail), and just a swig issue.
It appears that any use of a template inside a template declaration does not work.
This is with swig 1.3.33 and before.
Thanks.
Marcus Mendenhall
Logged In: YES
user_id=242951
Originator: NO
Template template parameters are supported, you've just hit a case that somehow we havn't tested before. Until this is fixed, you can drop 'float_type' in the template template parameter and SWIG will then parse it:
template <typename float_type, template <typename> class c2_class > class c2_typed_ptr : public c2_const_ptr<float_type> {};
I think that most people usually leave it out as it is not needed in this context.
Logged In: YES
user_id=470295
Originator: YES
OK, thanks. Some previous versions of SWIG choked on template <typename> (with no dummy name specified), so I hadn't gone back to try this.
However, fixing this exposed a different, somewhat related bug... from a class which starts out like:
template <typename float_type, template <typename> class c2_class > class c2_typed_ptr : public c2_const_ptr<float_type> {
public:
/// \brief construct the container with no function
c2_typed_ptr() : c2_ptr<float_type>() {}
/// \brief construct the container with a pre-defined function
/// \param f the function to store
c2_typed_ptr(c2_class<float_type> &f)
: c2_const_ptr<float_type>() { this->set_function(&f); }
}
and templatized as:
%template(interp_ptr) c2_typed_ptr<double, interpolating_function_p>;
I get the following code in my wrapper, which explicitly uses the template dummy typename c2_class instead of the declared interpolating_function_p:
SWIGINTERN PyObject *_wrap_new_interp_ptr__SWIG_1(PyObject *SWIGUNUSEDPARM(self), int nobjs, PyObject **swig_obj) {
PyObject *resultobj = 0;
c2_class<double > *arg1 = 0 ;
c2_typed_ptr<double,interpolating_function_p > *result = 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
Logged In: YES
user_id=242951
Originator: NO
Resolution of the template template type does not seem to be working. Looks similar to the issue noted in the fairly new template_template_parameters.i testcase.
Standalone testcase for the two problems reported:
#if 0
// Problem 1
%inline %{
template <typename T> class c2_const_ptr {};
template <typename float_type, template <typename> class c2_class > class c2_typed_ptr : public c2_const_ptr<float_type>
{};
%}
%template(c2const) c2_const_ptr<double>;
%template(mytemplate) c2_typed_ptr<double, c2_const_ptr>;
#endif
// Problem 2
%inline %{
template <typename float_type> class interpolating_function_p {};
template <typename T> class c2_const_ptr {};
%}
%template(c2const) c2_const_ptr<double>;
%inline %{
template <typename float_type, template <typename> class c2_class > class c2_typed_ptr : public c2_const_ptr<float_type> {
public:
/// \brief construct the container with no function
// c2_typed_ptr() : c2_ptr<float_type>() {}
c2_typed_ptr() : c2_const_ptr<float_type>() {}
/// \brief construct the container with a pre-defined function
/// \param f the function to store
c2_typed_ptr(c2_class<float_type> &f) : c2_const_ptr<float_type>() {}
};
%}
%template(interp_ptr) c2_typed_ptr<double, interpolating_function_p>;
Logged In: YES
user_id=2202676
Originator: NO
According to this thread :
http://sourceforge.net/mailarchive/forum.php?thread_name=48BD4DE5.3030509%40yahoo.fr&forum_name=swig-user
Here is another simple testcase. In this case, swig produces a "9: Error: Syntax error in input(1)" error at parse time (swig -v -c++ -python testcase.i) :
%inline %{
template <class elementT> class parentT {};
typedef parentT<float> parentF;
%}
%template(parentF) parentT<float>;
%inline %{
template<template <class elementT> class parentT> class childT : public parentT<elementT> {};
typedef childT<parentF> childF;
%}
%template(childF) childT<parentF>;
HTH,
Tonio
Atop SWIG 2.0.3 I can confirm Marcus' secondary comment that "[he gets] the following code in my wrapper, which explicitly uses the template dummy typename c2_class instead of the declared interpolating_function_p...". I have run into the same issue.
A (different) small recreate of this secondary issue:
// BEGIN foo.cpp
template<typename T>
struct Foo {
T foo;
};
template<template <typename> class U, typename T>
struct Bar {
U<T> bar;
};
int main()
{
Bar<Foo,int> b;
b.bar.foo = 6;
return 0;
}
// END foo.cpp
// BEGIN foo.i
%module test
%include foo.cpp
%template() Foo<int>;
%template(Baz) Bar<Foo,int>;
%ignore main;
// END foo.i
Using SWIG 2.0.3 execute 'swig -c++ -python foo.i' and observe that within foo_wrap.cxx's method _wrap_Baz_bar_set() there's an incorrect usage of ' U< int > arg2 ;'
I expect that having declared Bar<Foo,int> that I would see 'Foo< int > arg2;' in the generated source.
foo_wrap.cxx contains a nekkid
SWIGINTERN PyObject *_wrap_Baz_bar_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
Bar< Foo,int > *arg1 = (Bar< Foo,int > *) 0 ;
U< int > arg2 ;
The example at the top still fails with current git master, but works with William's tweak.
SWIG git master now processes the original example here. I suspect this is the fix (which will be in SWIG 4.2.0):