element typemap + stl_vector.i typemap + ??? --> wrapped function taking list of elems
Question: Let's say I have an arbitrary non-trivial type `A` that I can write typemaps
for. In particular, let's say that I know how to convert `std::strings` into
`A` and that I have typemaps from strings in the target language to `A`. I
import `stl_vector.i` and `%template(AVector) std::vector<A>;`.

What's the quickest/easiest (or even the 'right') course of action in SWIG to
having a function wrapper of `void func(const std::vector<A>& vals)` where the
expected input on the target language side is a list of strings (e.g. `['a',
'qqq']` in Python)? Unless I'm mistaken it doesn't appear to Just Work™
(specifically, nowhere in generated wrapper code have I seen the typemap code
for `A`).

If you _need_ a specific target language to answer, let's say it's Python. I'd
rather be able to do this in the general case, though...


Answer: Assuming we have a header file that looks like:

    
    
    #ifndef TEST_H
    #define TEST_H
    
    #include <iostream>
    #include <functional>
    #include <iterator>
    
    struct A {
      A(const std::string& v) : val(v) {}
      A(const A&) = default;
      A() = default;
      std::string val;
    };
    
    inline std::ostream& operator<<(std::ostream& in, const A& o) {
      return in << o.val;
    }
    
    inline void run(const std::vector<A>& in) {
      std::copy(in.begin(), in.end(), std::ostream_iterator<A>(std::cout, "\n"));
    }    
    #endif
    

We want to wrap it such that `run` can be called with a list of strings, or a
`std::vector<A>` interchangeably.

Given that language agnosticism is a stated goal the best way to achieve this
is by introducing a little more C++, to help with some type conversions and an
overload.

We can wrap the header file initially with something simple like:

    
    
    %module test
    
    %include <std_vector.i>
    %include <std_string.i>
    
    %{
    #include "test.h"
    %}
    
    %template(AVec) std::vector<A>;
    
    %include "test.h"
    

Which is then sufficient to run the first half of our Python test case:

    
    
    import test
    
    test.A("")
    
    v1=test.AVec(2,test.A("testing"))
    print type(v1)
    test.run(v1)
    
    # Here onwards needs some more work though...
    v2=["hello", "world", "isn't", "this", "fun"]
    print type(v2)
    test.run(v2)
    

To start working with the second half of this test case we need to adapt the
SWIG interface. I'm going to do this by adding a function, internal to the
wrapper and an overload that takes advantage of SWIG's default typemaps for
`std::vector<std::string>`.

By adding:

    
    
    %{
    // Some glue to trivially convert types
    std::vector<A> convert(const std::vector<std::string>& in) {
      std::vector<A> ret;
      std::copy(in.begin(), in.end(), std::back_inserter(ret));
      return ret;
    }
    %}
    
    %inline %{
    // An overload.
    void run(const std::vector<std::string>& in) {
      run(convert(in));
    }
    %}
    

To the end of the initial SWIG interface we've added an overload that works
provided the target language has a suitable understanding of `std::vector`.
(Most that I checked seem to).

With the version of SWIG that I tested this with running SWIG itself with
warnings turned on gave a (spurious) warning about shadowing overloads. This
warning seems to be incorrect, because the code generated really did pick the
correct overload, based on the argument given.

Using overloads added with `%inline` in the interface file is by far the
quickest/easiest way to get this up and running. It does of course require the
copy/conversion overhead _and_ writing the overloads manually per function.
Doing it with a typemap would only require writing a single typemap, but would
be very hard to do in a way that is independent of the target language.

