Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wrapping specialised c++ template class with swig

consider the following class declarations:

namespace X {
template<class T>
class Foo {
public:
    Foo();
    virtual ~Foo();

    T value() const;
};

template<class T>
class Foo<vector<T>> {
public:
    Foo();
    virtual ~Foo();

    T value( const int ) const;
};
}

for them i have the following declaration in the foo.i file

%include "stl.i"
%include "std_string.i"
%include "std_vector.i"

namespace X {
using namespace std;

template<class T>
class Foo {
public:
    Foo();
    virtual ~Foo();
    T value() const;
};

template<class T>
class Foo<vector<T> > {
public:
    Foo();
    virtual ~Foo();
    T value( const int ) const;
};

%template(FooInt) Foo<int>;
%template(FooString) Foo<string>;
%template(FooVectorInt) Foo<vector<int> >;

}

the difference between the two classes is the specialisation of the later to vector container and the differrent signature of the value() method, where the first takes no arguments, while the second takes an expects an integer.

the wrapper code put together by swig wrapps the %template(FooVectorInt) wrong, in that it calls the value() method instead that of the specialised vector method value(const int). giving me the following compile error message:

foo_wrap.cxx: in function »int _wrap_FooVectorInt_value(lua_State*)«:

/home/noobsaibot/foo/bindings/src/lua/foo_wrap.cxx:6706:81: error: no matching function to call »X::Foo<std::vector<int> >::value() const«
/home/noobsaibot/foo/src/foo.h:78:5: note: candidate is: T X::Foo<std::vector<_RealType> >::value(int) const [with T = int, int = unsigned int]

any advices as to what i might be missing to make swig understand which function is the correct one?

cheers

like image 653
noobsaibot Avatar asked Oct 09 '22 09:10

noobsaibot


1 Answers

You can achieve the result you want by doing:

%include "stl.i"
%include "std_string.i"
%include "std_vector.i"

namespace X {
using namespace std;

%rename(FooVectorInt) Foo<std::vector<int> >;

class Foo<std::vector<int> > {
public:
    virtual ~Foo();
    int value( const int ) const;
};

template<class T>
class Foo {
public:
    Foo();
    virtual ~Foo();
    T value() const;
};

%template(FooInt) Foo<int>;
%template(FooString) Foo<string>;
}

This works because what you write in the interface file isn't C++ and all that matters is that the correct code is generated by SWIG. If you want to repeat this lots you can write macros (which is close to what %template is anyway).

Still this isn't a very clean solution - I expected this to "just work" with the specialisations and I can't see a simpler workaround either.

like image 156
Flexo Avatar answered Oct 13 '22 12:10

Flexo