Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

#880 swig chokes on c++ template< template...> >

open
nobody
parsing (147)
5
2007-12-31
2007-12-31
No

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

Discussion

  • William Fulton
    William Fulton
    2007-12-31

    • labels: --> parsing
     
  • William Fulton
    William Fulton
    2007-12-31

    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 ;

     
  • William Fulton
    William Fulton
    2007-12-31

    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>;

     
  • aprevot
    aprevot
    2008-09-03

    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

     
  • Rhys Ulerich
    Rhys Ulerich
    2011-05-22

    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 ;