diff options
Diffstat (limited to 'Examples/test-suite/cpp11_move_only_valuewrapper.i')
-rw-r--r-- | Examples/test-suite/cpp11_move_only_valuewrapper.i | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/Examples/test-suite/cpp11_move_only_valuewrapper.i b/Examples/test-suite/cpp11_move_only_valuewrapper.i new file mode 100644 index 000000000..d9162bf3e --- /dev/null +++ b/Examples/test-suite/cpp11_move_only_valuewrapper.i @@ -0,0 +1,180 @@ +%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 <iostream> +#include <sstream> +using std::cout; +using std::endl; + +#if __cplusplus >= 201103L +#include <memory> +#else +namespace std { + // just something that will compile and vaguely work for when c++11 is not supported + template <class T> 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<unique_ptr &>(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<unique_ptr &>(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<XXX> makeUniqueXXX(); +void cleanup(std::unique_ptr<XXX>* p); + +%{ +std::unique_ptr<XXX> makeUniqueXXX() { + if (trace) cout << "makeUniqueXXX()" << endl; + return std::unique_ptr<XXX>(new XXX(11)); +} +void cleanup(std::unique_ptr<XXX>* 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<XXX> 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<XXX> 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<XXX> 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<std::unique_ptr<XXX> > x; + x = std::unique_ptr<XXX>(new XXX(444)); + } + Counter::check_counts(1, 0, 0, 0, 0, 1); +} +void test5() { +#if __cplusplus >= 201103L + Counter::reset_counts(); + { + SwigValueWrapper<std::unique_ptr<XXX> > x; + x = std::unique_ptr<XXX>(new XXX(550)); + std::unique_ptr<XXX> 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<std::unique_ptr<XXX> > 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<XXX>(x); // 'out' typemap (move std::unique_ptr from stack to the heap) + delete (std::unique_ptr<XXX> *)ptr; // Final cleanup (user needs to call this) + } + Counter::check_counts(1, 0, 0, 0, 0, 1); +#endif +} +%} |