swig/Examples/test-suite/cpp11_template_pack_special...

144 lines
4.1 KiB
OpenEdge ABL

%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)>;