| %module cpp11_template_pack_specialization | |
| %include <std_string.i> | |
| %inline %{ | |
| #include <string> | |
| template <typename...> struct Pack {}; | |
| template <typename T> struct SomeParms { | |
| void primary_method() {} | |
| }; | |
| template <typename... ARGS> struct SomeParms<Pack<ARGS...>> { | |
| void partial_method(ARGS...) {} | |
| }; | |
| template <typename T> struct SomeParms2 { | |
| void primary2_method() {} | |
| }; | |
| template <typename A, typename... ARGS> struct SomeParms2<Pack<A, ARGS...>> { | |
| void partial2_methodA(ARGS...) {} | |
| void partial2_methodB(A, ARGS...) {} | |
| void partial2_methodC(A) {} | |
| }; | |
| void checker() { | |
| SomeParms<int> spi; | |
| spi.primary_method(); | |
| SomeParms<Pack<>> spp; | |
| spp.partial_method(); | |
| SomeParms<Pack<std::string>> sps; | |
| sps.partial_method("hello"); | |
| SomeParms<Pack<int, double>> spid; | |
| spid.partial_method(10, 11.1); | |
| SomeParms2<Pack<int>> sp2i; | |
| sp2i.partial2_methodC(20); | |
| SomeParms2<Pack<int, double>> sp2id; | |
| sp2id.partial2_methodA(11.1); | |
| sp2id.partial2_methodB(55, 11.1); | |
| sp2id.partial2_methodC(55); | |
| SomeParms2<Pack<int, double, float>> sp2idf; | |
| sp2idf.partial2_methodA(11.1, 22.2f); | |
| sp2idf.partial2_methodB(55, 11.1, 22.2f); | |
| sp2idf.partial2_methodC(55); | |
| } | |
| %} | |
| %template(SomeParmsInt) SomeParms<int>; | |
| %template(PackIntNoParms) Pack<>; | |
| %template(SomeParmsNoParms) SomeParms<Pack<>>; | |
| %template(PackIntString) Pack<std::string>; | |
| %template(SomeParmsString) SomeParms<Pack<std::string>>; | |
| %template(PackIntDouble) Pack<int, double>; | |
| %template(SomeParmsIntDouble) SomeParms<Pack<int, double>>; | |
| %template(SomeParms2PackInt) SomeParms2<Pack<int>>; | |
| %template(SomeParms2PackIntDouble) SomeParms2<Pack<int, double>>; | |
| %template(SomeParms2PackIntDoubleFloat) SomeParms2<Pack<int, double, float>>; | |
| %rename(call) *::operator(); | |
| %inline %{ | |
| // StdFunction is similar to std::function | |
| template <typename T> struct StdFunction { | |
| void primary_function() {} | |
| }; | |
| template <typename RET, typename... ARGS> class StdFunction<RET(ARGS...)> { | |
| public: | |
| using result_type = RET; | |
| StdFunction() = default; | |
| RET call_operator(ARGS... args) const { | |
| return operator() (args...); | |
| } | |
| // Sum the args | |
| RET operator()(ARGS... args) const { | |
| return sum(args...); | |
| } | |
| private: | |
| // Recursive sum helpers: | |
| // - zero args -> returns RET() | |
| // - one arg -> returns single arg | |
| // - many args -> returns first + sum(rest...) | |
| RET sum() const { return RET(); } | |
| template <typename A> RET sum(A a) const { return static_cast<RET>(a); } | |
| template <typename A, typename B, typename... Rest> RET sum(A a, B b, Rest... rest) const { return static_cast<RET>(a + sum(b, rest...)); } | |
| }; | |
| %} | |
| %inline %{ | |
| bool function_checker() { | |
| bool okay = true; | |
| StdFunction<int(int, int)> f_int; | |
| int result = f_int(10, 20); | |
| okay = result == 30; | |
| result = f_int.call_operator(20, 30); | |
| okay = okay && result == 50; | |
| // Zero parameters - returns int{} == 0 | |
| StdFunction<int()> f_int0; | |
| okay = okay && f_int0() == 0; | |
| okay = okay && f_int0.call_operator() == 0; | |
| // Single parameter - the unary fold yields the single arg | |
| StdFunction<int(int)> f_int1; | |
| okay = okay && f_int1(7) == 7; | |
| okay = okay && f_int1.call_operator(7) == 7; | |
| // Different result/argument types | |
| StdFunction<double(double, double)> f_double; | |
| okay = okay && f_double(1.5, 2.25) == 3.75; | |
| okay = okay && f_double.call_operator(1.5, 2.25) == 3.75; | |
| StdFunction<std::string(std::string, std::string)> f_string; | |
| okay = okay && f_string(std::string("ab"), std::string("cd")) == std::string("abcd"); | |
| okay = okay && f_string.call_operator(std::string("ab"), std::string("cd")) == std::string("abcd"); | |
| // Mixed argument types (int + double promotes to double; assigned back to int) | |
| StdFunction<int(int, double, int)> f_mixed; | |
| okay = okay && f_mixed(1, 2.0, 3) == 6; | |
| okay = okay && f_mixed.call_operator(1, 2.0, 3) == 6; | |
| return okay; | |
| } | |
| %} | |
| %template(StdFunctionVoid) StdFunction<int()>; | |
| %template(StdFunctionInt) StdFunction<int(int)>; | |
| %template(StdFunctionIntInt) StdFunction<int(int, int)>; | |
| %template(StdFunctionDoubleDouble) StdFunction<double(double, double)>; | |
| %template(StdFunctionStringString) StdFunction<std::string(std::string, std::string)>; | |
| %template(StdFunctionMixed) StdFunction<int(int, double, int)>; |