%module cpp11_move_only_valuewrapper /* * This test case checks SwigValueWrapper and move assignment. * Although not necessary, the test case was developed testing with C++98 compatibility for comparing improvements. * C++11 and later is of course required for the move assignment support. * C++98 is not actually necessary now as the test-suite only runs this test with compilers that support C++11 and later. */ %{ #include #include using std::cout; using std::endl; #if __cplusplus >= 201103L #include #else namespace std { // just something that will compile and vaguely work for when c++11 is not supported template class unique_ptr { T *ptr; public: unique_ptr(T *ptr = 0) : ptr(ptr) {} unique_ptr(const unique_ptr &a) : ptr(a.ptr) { /*please look away*/ const_cast(a).ptr = 0;} ~unique_ptr() { delete ptr; } unique_ptr& operator=(const unique_ptr &a) { if (&a != this) { delete ptr; ptr = a.ptr; /*please look away*/ const_cast(a).ptr = 0; } return *this; } }; } #endif %} %include "cpp11_move_only_helper.i" %valuewrapper XXX; %ignore XXX::operator=; %inline %{ bool trace = false; struct XXX { XXX(int i = 0) { if (trace) cout << "XXX(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } XXX(const XXX &other) { if (trace) cout << "XXX(const XXX &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;} XXX & operator=(const XXX &other) { if (trace) cout << "operator=(const XXX &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; } #if defined(__cplusplus) && __cplusplus >= 201103L XXX(XXX &&other) noexcept { if (trace) cout << "XXX(XXX &&)" << " " << this << endl; Counter::move_constructor++; } XXX & operator=(XXX &&other) noexcept { if (trace) cout << "operator=(XXX &&)" << " " << this << endl; Counter::move_assignment++; return *this; } #endif ~XXX() { if (trace) cout << "~XXX()" << " " << this << endl; Counter::destructor++; } }; bool has_cplusplus11() { #if __cplusplus >= 201103L return true; #else return false; #endif } %} std::unique_ptr makeUniqueXXX(); void cleanup(std::unique_ptr* p); %{ std::unique_ptr makeUniqueXXX() { if (trace) cout << "makeUniqueXXX()" << endl; return std::unique_ptr(new XXX(11)); } void cleanup(std::unique_ptr* p) { delete p; } typedef XXX UUU; %} %inline %{ XXX createXXX() { if (trace) cout << "createXXX()" << endl; return XXX(111); } XXX createXXX2() { if (trace) cout << "createXXX2()" << endl; return XXX(222); } UUU createUnknownType() { if (trace) cout << "createXXX2()" << endl; return XXX(222); } struct YYY {}; void inputByValue(UUU uuu, XXX xxx, YYY yyy) {} %} %catches(std::string) test1; %catches(std::string) test2; %catches(std::string) test3; %catches(std::string) test4; %catches(std::string) test5; %catches(std::string) test6; %inline %{ // 'unit tests' for SwigValueWrapper void test1() { Counter::reset_counts(); { SwigValueWrapper x; x = XXX(); } #if __cplusplus >= 201103L Counter::check_counts(1, 0, 0, 1, 0, 2); // was same as < c++11 counts below before move assignment operator added to SwigValueWrapper #else Counter::check_counts(1, 1, 0, 0, 0, 2); #endif } void test2() { Counter::reset_counts(); { SwigValueWrapper x; x = XXX(); x = XXX(); } #if __cplusplus >= 201103L Counter::check_counts(2, 0, 0, 2, 0, 4); #else Counter::check_counts(2, 2, 0, 0, 0, 4); #endif } void test3() { Counter::reset_counts(); { SwigValueWrapper x; XXX a(999); #if __cplusplus >= 201103L x = std::move(a); #endif } #if __cplusplus >= 201103L Counter::check_counts(1, 0, 0, 1, 0, 2); #endif } void test4() { Counter::reset_counts(); { SwigValueWrapper > x; x = std::unique_ptr(new XXX(444)); } Counter::check_counts(1, 0, 0, 0, 0, 1); } void test5() { #if __cplusplus >= 201103L Counter::reset_counts(); { SwigValueWrapper > x; x = std::unique_ptr(new XXX(550)); std::unique_ptr x2(new XXX(555)); x = std::move(x2); } Counter::check_counts(2, 0, 0, 0, 0, 2); #endif } void test6() { #if __cplusplus >= 201103L Counter::reset_counts(); { // emulates how std::unique_ptr typemaps could be wrapped with SwigValueWrapper void *ptr = 0; SwigValueWrapper > x; // SWIG generated if std::unique_ptr<> definition not parsed x = makeUniqueXXX(); // SWIG generated code wrapping function returning std::unique_ptr ptr = new std::unique_ptr(x); // 'out' typemap (move std::unique_ptr from stack to the heap) delete (std::unique_ptr *)ptr; // Final cleanup (user needs to call this) } Counter::check_counts(1, 0, 0, 0, 0, 1); #endif } %}