I have a header file containing the definition of a variadic template, which also contains a few variadic templated member functions. Code snippets below have been significantly simplified and cut down for brevity:
#pragma once
template<typename T, typename ... CtorArgs>
class Foo {
public:
Foo(CtorArgs... args) : _m(args...) {}
template<typename ... Args>
void DoSomething(Args... args) { _m.DoSomething(args...); }
private:
T _m;
};
I then have another header defining a class to be used in a template specialization:
#pragma once
#include <string>
#include <iostream>
class Bar {
public:
Bar(std::string const & a,
std::string const & b) :
m_strA(a),
m_strB(b) {}
void DoSomething(int const one, int const two) {
std::cout << "Str A: " << m_strA << ", Str B: "<< m_strB << ", ints: " << one << ", " << two << std::endl;
}
private:
std::string m_strA;
std::string m_strB;
};
I would like to wrap the Foo specialization using SWIG, as well as its templated member function, so I can use them from a Lua script.
The problem I am encountering is that SWIG is not generating a wrapper for the DoSomething templated function as I expect.
After reading some of the SWIG documentation, I am aware that it is unable to use the %template directive with more than 1 substitution for the parameter pack arguments, so I have used %rename instead:
%module FooSwig
%include <std_string.i>
%{
#include "foo.hpp"
#include "bar.hpp"
%}
%include "foo.hpp"
%include "bar.hpp"
%rename(lua_foo) Foo<Bar, std::string const &, std::string const &>;
class Foo<Bar, std::string const &, std::string const &> {
public:
Foo(std::string const &, std::string const &);
template<typename ... Args>
void DoSomething(Args... args);
private:
Bar _m;
};
Using the %template directive doesn't work (as expected), as there are more than 1 parameters to substitute - I get the following from swig:
Error: Template 'DoSomething' undefined.
I imagine I need to get around this using %rename again, but I can't figure out how. I've tried the following:
%extend Foo<Bar, std::string const &, std::string const &>
{
%rename(Do_Something) DoSomething<int const, int const>;
void DoSomething(int const, int const);
}
And that does generate something, but the wrapper contains a symbol for a function that is undefined:
Foo_Sl_Bar_Sc_std_string_SS_const_SA__Sc_std_string_SS_const_SA__Sg__DoSomething(arg1,arg2,arg3);
instead of the expected call to a member function template, something along the lines of
(arg1)->SWIGTEMPLATEDISAMBIGUATOR DoSomething<int const, int const>(arg2, arg3);
I'm running out of things to try, and maybe one of you can help?
Some info about my environment: I'm using g++ 7.4.0, c++ 17 and SWIG 3.0.
I managed to get the wrapper generated and it works as expected.
This is a snippet of the old SWIG interface file:
...
template<typename ... Args>
void DoSomething(Args... args);
...
I replaced it with the following:
...
void DoSomething(int const, int const);
...
However I am still curious to find out whether there is a better way to do it so any further info (or pointers to reading materials/source code) would be appreciated.