You can distribute whole patterns without having to select a specific type. For example, changing the code as follows:
%module test %{ #include <vector> %} %inline %{ template<typename T> class Array1D{ private: std::vector<T> data_; size_t xsize_; public: Array1D(): xsize_(0) {}; // creates vector of size nx and sets each element to t Array1D(const size_t& nx, const T& t): xsize_(nx) { data_.resize(xsize_, t); } T& operator[](const size_t i) {return data_.at(i);} }; %} %extend Array1D { T __getitem__(size_t i) { return (*$self)[i]; } } %template(intArray1D) Array1D<int>; %template(doubleArray1D) Array1D<double>;
It works as you hope, because SWIG itself extends and populates the types for T when it creates a wrapper:
In [1]: import test In [2]: a=test.intArray1D(10,1) In [3]: a[0] Out[3]: 1 In [4]: a[10] terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check zsh: abort ipython
Note. I changed to size_t with int , because they are not always synonymous and .at() instead of [] , because the first will cause an invalid index, and not cause undefined behavior. In fact, you can use the default SWIG exception library for smart things with the exception for free:
%module test %{ #include <vector> %} %include <std_except.i> %inline %{ template<typename T> class Array1D{ private: std::vector<T> data_; size_t xsize_; public: Array1D(): xsize_(0) {}; // creates vector of size nx and sets each element to t Array1D(const size_t& nx, const T& t): xsize_(nx) { data_.resize(xsize_, t); } T& operator[](const size_t i) {return data_.at(i);} }; %} %extend Array1D { T __getitem__(size_t i) throw(std::out_of_range) { return (*$self)[i]; } } %template(intArray1D) Array1D<int>; %template(doubleArray1D) Array1D<double>;
Enough (two lines of changes) to get a Python IndexError instead of a C ++ exception, crash, or other UB.
Flexo source share