Menu

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

None
closed-fixed
nobody
parsing (146)
5
2022-12-07
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.

     
  • Marcus Mendenhall

    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 ;

     
  • Olly Betts

    Olly Betts - 2022-01-28

    The example at the top still fails with current git master, but works with William's tweak.

     
  • Olly Betts

    Olly Betts - 2022-12-07
    • status: open --> closed-fixed
    • Group: -->
     
  • Olly Betts

    Olly Betts - 2022-12-07

    SWIG git master now processes the original example here. I suspect this is the fix (which will be in SWIG 4.2.0):

    2022-12-02: wsfulton                                                            
                #624 #1021 Improved template template parameters support. Previously, specifying more                                                               
                than one simple template template parameter resulted in a parse error. Now                                                                          
                multiple template template parameters are working including instantiation with                                                                      
                %template. Example:                                                 
    
                  template <template<template<class> class, class> class Op, template<class> class X, class Y>                                                      
                  class C { ... };
    
     

Log in to post a comment.