rvalue reference outputs

Document rvalue reference outputs behaviour
Test rvalue reference outputs
This commit is contained in:
William S Fulton 2022-09-08 08:46:32 +01:00
parent c5495fea79
commit 2212af3f4f
26 changed files with 659 additions and 344 deletions

View File

@ -16,6 +16,8 @@
<ul>
<li><a href="#CPlusPlus11_rvalue_reference_and_move_semantics">Rvalue reference and move semantics</a>
<ul>
<li><a href="#CPlusPlus11_rvalue_reference_inputs">Rvalue reference inputs</a>
<li><a href="#CPlusPlus11_rvalue_reference_outputs">Rvalue reference outputs</a>
<li><a href="#CPlusPlus11_move_only">Movable and move-only types</a>
</ul>
<li><a href="#CPlusPlus11_generalized_constant_expressions">Generalized constant expressions</a>
@ -109,7 +111,7 @@ public:
<p>
Rvalue references are designed for C++ temporaries and are not particularly useful when used from non-C++ target languages.
You could just ignore them via <tt>%ignore</tt> before parsing the class.
One option is to just ignore them via <tt>%ignore</tt>.
For example, ignore the move constructor:
</p>
@ -117,8 +119,17 @@ For example, ignore the move constructor:
%ignore MyClass::MyClass(MyClass &amp;&amp;);
</pre></div>
<H4><a name="CPlusPlus11_rvalue_reference_inputs">7.2.1.1 Rvalue reference inputs</a></H4>
<p>
However, if you do wrap a function/contructor with an rvalue reference and pass a proxy class to it, SWIG will assume that after the call, the rvalue reference parameter will have been 'moved'.
Rvalue reference parameters are useful as input parameters in C++ for implementing move semantics, such as,
in the move constructor and move assignment operator.
This type of usage can be useful from target languages too to avoid copying large objects.
</p>
<p>
If you do wrap a function/contructor with an rvalue reference parameter and pass a proxy class to it, SWIG will assume that after the call, the rvalue reference parameter object will have been 'moved'.
The proxy class passed as the rvalue reference, will own the underlying C++ object up until it is used as an rvalue reference parameter.
Afterwards, the proxy class will have the underlying C++ pointer set to the nullptr so that the proxy class instance cannot be used again and the underlying (moved from) C++ object will be deleted after the function/constructor call has returned.
</p>
@ -136,15 +147,15 @@ MyClass mc2 = new MyClass(mc); // move constructor fails
<p>
The second call to the move constructor will fail as the <tt>mc</tt> proxy instance has been moved.
Each target language handles the moved proxy class slightly differently, but typically you'll get an exception such as in Java:
Each target language handles the moved proxy class slightly differently when attempting to move it again, but typically you'll get an exception such as in Java:
</p>
<div class="shell">
<pre>
Exception in thread "main" java.lang.RuntimeException: Cannot release ownership as memory is not owned
at MyClass.swigRelease(MyClass.java:27)
at MyClass.<init>(MyClass.java:55)
at runme.main(runme.java:18)
at MyClass.swigRelease(MyClass.java:27)
at MyClass.&lt;init&gt;(MyClass.java:55)
at runme.main(runme.java:18)
</pre>
</div>
@ -160,15 +171,15 @@ example.i:18: Warning 503: Can't wrap 'operator =' unless renamed to a valid ide
</div>
<p>
Using a <tt>%rename</tt> will remove the warning, however, a <tt>%rename</tt> makes the move constructor available from the target language:
Using a <tt>%rename</tt> will remove the warning and also makes the move assignment operator available from the target language:
</p>
<div class="code"><pre>
%rename(MoveAssign) MyClass::operator=(MyClass &amp;&amp;);
</pre></div>
<p>
You can then use the move assignment operator, but like the move constructor example above, you cannot use
a proxy class once it has been moved:
You can then use it, but like the move constructor example above, you cannot use
a proxy class once it has already been moved:
</p>
<div class="targetlang"><pre>
@ -178,12 +189,58 @@ MyClass mc3 = mc.MoveAssign(mc); // Use of mc again will fail
</pre></div>
<p>
<b>Compatibility note:</b>
SWIG-4.1.0 changed the way that rvalue references were handled and implemented typemaps assuming that the
proxy class would transfer ownership of the underlying C++ object when a function/constructor with an rvalue reference parameter was called.
It is of course perfectly possible in C++ for a function/constructor to not move an object passed to it in an rvalue reference parameter. The assumption that SWIG makes would then not hold and customisation of the appropriate input typemaps would be required.
For scripting languages, this would be for the 'in' typemap and for the non-scripting languages additional typemaps such as the 'javain' typemap, which is used to set the memory ownership of the underlying C++ object for Java, would also need copying and modifying appropriately.
</p>
<H4><a name="CPlusPlus11_move_only">7.2.1.1 Movable and move-only types</a></H4>
<p>
<b>Compatibility note:</b>
SWIG-4.1.0 changed the way that rvalue reference parameters were handled and implemented typemaps assuming that the
proxy class owns the underlying C++ object and transfers ownership of the object when a function/constructor with an rvalue reference parameter is called.
</p>
<H4><a name="CPlusPlus11_rvalue_reference_outputs">7.2.1.2 Rvalue reference outputs</a></H4>
<p>
While rvalue reference parameter inputs are not uncommon in C++ and can be usefully utilised from target languages, this cannot be said for rvalue reference outputs.
Firstly, it is quite unusual in C++ to have functions that return an rvalue reference.
Secondly, these cases are nigh on impossible to use from a target language.
The main problem is these references are for C++ compiler temporaries used on the stack and the target languages use objects on the heap
and the concept of compiler temporary objects doesn't make sense from another language.
</p>
<p>
Using <tt>MyClass</tt> from earlier and this C++ code:
</p>
<div class="code"><pre>
void use(MyClass &amp;&amp;mc);
MyClass &amp;&amp; get1();
MyClass &amp; get2();
</pre></div>
<p>
SWIG wraps the <tt>get1</tt> and <tt>get2</tt> functions more or less identically.
The returned references are converted into pointers that are not owned by the target language.
It means that the following perfectly valid C++ has no equivalent in any of the target languages:
</p>
<div class="code"><pre>
use(get1());
use(std::move(get2()));
</pre></div>
<p>
An attempt to call the equivalent <tt>use(get1())</tt> from one of the target languages will result in the ownership failure mentioned in the previous section as the object being passed to the <tt>use</tt> function is not owned by the proxy class.
In order to own the object, it would need to be cloned for the object to move from the stack to the heap, for which an appropriate clone function would be required, but may not even be available.
Note that a move constructor or copy constructor may slice the object when inheritance is involved.
Alternatively, customising the input rvalue reference typemap, as mentioned in the previous section, could remove the ownership requirement.
Another alternative would be to modify the output rvalue reference typemap to always clone the rvalue reference object.
Fortunately you're highly unlikely to have to solve any of these issues!
</p>
<H4><a name="CPlusPlus11_move_only">7.2.1.3 Movable and move-only types</a></H4>
<p>

View File

@ -298,6 +298,8 @@
<ul>
<li><a href="CPlusPlus11.html#CPlusPlus11_rvalue_reference_and_move_semantics">Rvalue reference and move semantics</a>
<ul>
<li><a href="CPlusPlus11.html#CPlusPlus11_rvalue_reference_inputs">Rvalue reference inputs</a>
<li><a href="CPlusPlus11.html#CPlusPlus11_rvalue_reference_outputs">Rvalue reference outputs</a>
<li><a href="CPlusPlus11.html#CPlusPlus11_move_only">Movable and move-only types</a>
</ul>
<li><a href="CPlusPlus11.html#CPlusPlus11_generalized_constant_expressions">Generalized constant expressions</a>

View File

@ -609,7 +609,7 @@ CPP11_TEST_CASES += \
cpp11_rvalue_reference \
cpp11_rvalue_reference2 \
cpp11_rvalue_reference3 \
cpp11_rvalue_reference_move_input \
cpp11_rvalue_reference_move \
cpp11_sizeof_object \
cpp11_static_assert \
cpp11_std_array \

View File

@ -0,0 +1,52 @@
%module cpp11_rvalue_reference_move
// Testcase for testing rvalue reference input typemaps which assume the object is moved during a function call
%include "cpp11_move_only_helper.i"
%catches(std::string) MovableCopyable::check_numbers_match;
%rename(MoveAssign) MovableCopyable::operator=(MovableCopyable &&);
%ignore MovableCopyable::operator=(const MovableCopyable &); // ignore copy assignment operator, keep move assignment operator
%ignore MovableCopyable::MovableCopyable(const MovableCopyable &); // ignore copy constructor, keep the move constructor
%inline %{
#include <iostream>
using namespace std;
bool trace = false;
class MovableCopyable {
int num;
public:
MovableCopyable(int i = 0) : num(i) { if (trace) cout << "MovableCopyable(" << i << ")" << " " << this << endl; Counter::normal_constructor++; }
MovableCopyable(const MovableCopyable &other) : num(other.num) { if (trace) cout << "MovableCopyable(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;}
MovableCopyable & operator=(const MovableCopyable &other) { if (trace) cout << "operator=(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; num = other.num; return *this; }
MovableCopyable(MovableCopyable &&other) noexcept : num(std::move(other.num)) { if (trace) cout << "MovableCopyable(MovableCopyable &&)" << " " << this << endl; Counter::move_constructor++; }
MovableCopyable & operator=(MovableCopyable &&other) noexcept { if (trace) cout << "operator=(MovableCopyable &&)" << " " << this << endl; Counter::move_assignment++; num = std::move(other.num); return *this; }
~MovableCopyable() { if (trace) cout << "~MovableCopyable()" << " " << this << endl; Counter::destructor++; }
int getNum() { return num; }
static void movein(MovableCopyable &&mcin) {
MovableCopyable mc = std::move(mcin);
}
static MovableCopyable && moveout(int i) {
static MovableCopyable instance;
instance = MovableCopyable(i);
return std::move(instance);
}
static bool is_nullptr(MovableCopyable *p) {
return p == nullptr;
}
static void check_numbers_match(MovableCopyable *p, int expected_num) {
if (p->num != expected_num)
throw std::string("Numbers don't match");
}
};
%}

View File

@ -1,37 +0,0 @@
%module cpp11_rvalue_reference_move_input
// Testcase for testing rvalue reference input typemaps which assume the object is moved during a function call
%include "cpp11_move_only_helper.i"
%rename(MoveAssign) MovableCopyable::operator=(MovableCopyable &&);
%ignore MovableCopyable::operator=(const MovableCopyable &); // ignore copy assignment operator, keep move assignment operator
%ignore MovableCopyable::MovableCopyable(const MovableCopyable &); // ignore copy constructor, keep the move constructor
%inline %{
#include <iostream>
using namespace std;
bool trace = false;
class MovableCopyable {
public:
MovableCopyable(int i = 0) { if (trace) cout << "MovableCopyable(" << i << ")" << " " << this << endl; Counter::normal_constructor++; }
MovableCopyable(const MovableCopyable &other) { if (trace) cout << "MovableCopyable(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;}
MovableCopyable & operator=(const MovableCopyable &other) { if (trace) cout << "operator=(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; }
MovableCopyable(MovableCopyable &&other) noexcept { if (trace) cout << "MovableCopyable(MovableCopyable &&)" << " " << this << endl; Counter::move_constructor++; }
MovableCopyable & operator=(MovableCopyable &&other) noexcept { if (trace) cout << "operator=(MovableCopyable &&)" << " " << this << endl; Counter::move_assignment++; return *this; }
~MovableCopyable() { if (trace) cout << "~MovableCopyable()" << " " << this << endl; Counter::destructor++; }
static void movein(MovableCopyable &&mcin) {
MovableCopyable mc = std::move(mcin);
}
static bool is_nullptr(MovableCopyable *p) {
return p == nullptr;
}
};
%}

View File

@ -1,7 +1,7 @@
using System;
using cpp11_rvalue_reference_move_inputNamespace;
using cpp11_rvalue_reference_moveNamespace;
public class cpp11_rvalue_reference_move_input_runme {
public class cpp11_rvalue_reference_move_runme {
public static void Main() {
{
// Function containing rvalue reference parameter
@ -62,5 +62,25 @@ public class cpp11_rvalue_reference_move_input_runme {
throw new ApplicationException("Should have thrown null error");
Counter.check_counts(0, 0, 0, 0, 0, 0);
}
{
// output
Counter.reset_counts();
MovableCopyable mc = MovableCopyable.moveout(1234);
Counter.check_counts(2, 0, 0, 0, 1, 1);
MovableCopyable.check_numbers_match(mc, 1234);
bool exception_thrown = false;
try {
MovableCopyable.movein(mc);
} catch (ApplicationException e) {
if (!e.Message.Contains("Cannot release ownership as memory is not owned"))
throw new ApplicationException("incorrect exception message");
exception_thrown = true;
}
if (!exception_thrown)
throw new ApplicationException("Should have thrown 'Cannot release ownership as memory is not owned' error");
Counter.check_counts(2, 0, 0, 0, 1, 1);
}
}
}

View File

@ -1,7 +1,7 @@
module cpp11_rvalue_reference_move_input_runme;
module cpp11_rvalue_reference_move_runme;
import cpp11_rvalue_reference_move_input.Counter;
import cpp11_rvalue_reference_move_input.MovableCopyable;
import cpp11_rvalue_reference_move.Counter;
import cpp11_rvalue_reference_move.MovableCopyable;
void main() {
{
@ -63,4 +63,24 @@ void main() {
throw new Exception("Should have thrown null error");
Counter.check_counts(0, 0, 0, 0, 0, 0);
}
{
// output
Counter.reset_counts();
MovableCopyable mc = MovableCopyable.moveout(1234);
Counter.check_counts(2, 0, 0, 0, 1, 1);
MovableCopyable.check_numbers_match(mc, 1234);
bool exception_thrown = false;
try {
MovableCopyable.movein(mc);
} catch (Exception e) {
if (!canFind(e.msg, "Cannot release ownership as memory is not owned"))
throw new Exception("incorrect exception message: " ~ e.msg);
exception_thrown = true;
}
if (!exception_thrown)
throw new Exception("Should have thrown 'Cannot release ownership as memory is not owned' error");
Counter.check_counts(2, 0, 0, 0, 1, 1);
}
}

View File

@ -1,7 +1,7 @@
module cpp11_rvalue_reference_move_input_runme;
module cpp11_rvalue_reference_move_runme;
import cpp11_rvalue_reference_move_input.Counter;
import cpp11_rvalue_reference_move_input.MovableCopyable;
import cpp11_rvalue_reference_move.Counter;
import cpp11_rvalue_reference_move.MovableCopyable;
import std.algorithm;
void main() {
@ -64,4 +64,24 @@ void main() {
throw new Exception("Should have thrown null error");
Counter.check_counts(0, 0, 0, 0, 0, 0);
}
{
// output
Counter.reset_counts();
MovableCopyable mc = MovableCopyable.moveout(1234);
Counter.check_counts(2, 0, 0, 0, 1, 1);
MovableCopyable.check_numbers_match(mc, 1234);
bool exception_thrown = false;
try {
MovableCopyable.movein(mc);
} catch (Exception e) {
if (!canFind(e.msg, "Cannot release ownership as memory is not owned"))
throw new Exception("incorrect exception message: " ~ e.msg);
exception_thrown = true;
}
if (!exception_thrown)
throw new Exception("Should have thrown 'Cannot release ownership as memory is not owned' error");
Counter.check_counts(2, 0, 0, 0, 1, 1);
}
}

View File

@ -1,3 +0,0 @@
(dynamic-call "scm_init_cpp11_rvalue_reference_move_input_module" (dynamic-link "./libcpp11_rvalue_reference_move_input"))
(load "testsuite.scm")
(load "../schemerunme/cpp11_rvalue_reference_move_input.scm")

View File

@ -0,0 +1,3 @@
(dynamic-call "scm_init_cpp11_rvalue_reference_move_module" (dynamic-link "./libcpp11_rvalue_reference_move"))
(load "testsuite.scm")
(load "../schemerunme/cpp11_rvalue_reference_move.scm")

View File

@ -1,11 +1,11 @@
import cpp11_rvalue_reference_move_input.*;
import cpp11_rvalue_reference_move.*;
public class cpp11_rvalue_reference_move_input_runme {
public class cpp11_rvalue_reference_move_runme {
static {
try {
System.loadLibrary("cpp11_rvalue_reference_move_input");
System.loadLibrary("cpp11_rvalue_reference_move");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
@ -73,5 +73,25 @@ public class cpp11_rvalue_reference_move_input_runme {
throw new RuntimeException("Should have thrown null error");
Counter.check_counts(0, 0, 0, 0, 0, 0);
}
{
// output
Counter.reset_counts();
MovableCopyable mc = MovableCopyable.moveout(1234);
Counter.check_counts(2, 0, 0, 0, 1, 1);
MovableCopyable.check_numbers_match(mc, 1234);
boolean exception_thrown = false;
try {
MovableCopyable.movein(mc);
} catch (RuntimeException e) {
if (!e.getMessage().contains("Cannot release ownership as memory is not owned"))
throw new RuntimeException("incorrect exception message");
exception_thrown = true;
}
if (!exception_thrown)
throw new RuntimeException("Should have thrown 'Cannot release ownership as memory is not owned' error");
Counter.check_counts(2, 0, 0, 0, 1, 1);
}
}
}

View File

@ -1,67 +0,0 @@
var cpp11_rvalue_reference_move_input = require("cpp11_rvalue_reference_move_input");
{
// Function containing rvalue reference parameter
cpp11_rvalue_reference_move_input.Counter.reset_counts();
mo = new cpp11_rvalue_reference_move_input.MovableCopyable(222);
cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 0, 0, 0);
cpp11_rvalue_reference_move_input.MovableCopyable.movein(mo);
cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2);
if (!cpp11_rvalue_reference_move_input.MovableCopyable.is_nullptr(mo))
throw new Error("is_nullptr failed");
delete mo;
cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2);
}
{
// Move constructor test
cpp11_rvalue_reference_move_input.Counter.reset_counts();
mo = new cpp11_rvalue_reference_move_input.MovableCopyable(222);
cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 0, 0, 0);
mo_moved = new cpp11_rvalue_reference_move_input.MovableCopyable(mo);
cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 1);
if (!cpp11_rvalue_reference_move_input.MovableCopyable.is_nullptr(mo))
throw new Error("is_nullptr failed");
delete mo;
cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 1);
// delete mo_moved;
// cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2);
// Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete
cpp11_rvalue_reference_move_input.MovableCopyable.movein(mo_moved);
cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 2, 0, 3);
}
{
// Move assignment operator test
cpp11_rvalue_reference_move_input.Counter.reset_counts();
mo111 = new cpp11_rvalue_reference_move_input.MovableCopyable(111);
mo222 = new cpp11_rvalue_reference_move_input.MovableCopyable(222);
cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 0, 0);
mo111.MoveAssign(mo222);
cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 1);
if (!cpp11_rvalue_reference_move_input.MovableCopyable.is_nullptr(mo222))
throw new Error("is_nullptr failed");
delete mo222;
cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 1);
// delete mo111;
// cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 2);
// Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete
cpp11_rvalue_reference_move_input.MovableCopyable.movein(mo111);
cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 1, 1, 3);
}
{
// null check
cpp11_rvalue_reference_move_input.Counter.reset_counts();
exception_thrown = false;
try {
cpp11_rvalue_reference_move_input.MovableCopyable.movein(null);
} catch (e) {
if (!e.message.includes("invalid null reference"))
throw new Error("incorrect exception message " + e.message);
exception_thrown = true;
}
if (!exception_thrown)
throw new Error("Should have thrown null error");
cpp11_rvalue_reference_move_input.Counter.check_counts(0, 0, 0, 0, 0, 0);
}

View File

@ -0,0 +1,87 @@
var cpp11_rvalue_reference_move = require("cpp11_rvalue_reference_move");
{
// Function containing rvalue reference parameter
cpp11_rvalue_reference_move.Counter.reset_counts();
mo = new cpp11_rvalue_reference_move.MovableCopyable(222);
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 0, 0, 0);
cpp11_rvalue_reference_move.MovableCopyable.movein(mo);
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2);
if (!cpp11_rvalue_reference_move.MovableCopyable.is_nullptr(mo))
throw new Error("is_nullptr failed");
delete mo;
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2);
}
{
// Move constructor test
cpp11_rvalue_reference_move.Counter.reset_counts();
mo = new cpp11_rvalue_reference_move.MovableCopyable(222);
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 0, 0, 0);
mo_moved = new cpp11_rvalue_reference_move.MovableCopyable(mo);
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 1);
if (!cpp11_rvalue_reference_move.MovableCopyable.is_nullptr(mo))
throw new Error("is_nullptr failed");
delete mo;
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 1);
// delete mo_moved;
// cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2);
// Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete
cpp11_rvalue_reference_move.MovableCopyable.movein(mo_moved);
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 2, 0, 3);
}
{
// Move assignment operator test
cpp11_rvalue_reference_move.Counter.reset_counts();
mo111 = new cpp11_rvalue_reference_move.MovableCopyable(111);
mo222 = new cpp11_rvalue_reference_move.MovableCopyable(222);
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 0, 0);
mo111.MoveAssign(mo222);
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1);
if (!cpp11_rvalue_reference_move.MovableCopyable.is_nullptr(mo222))
throw new Error("is_nullptr failed");
delete mo222;
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1);
// delete mo111;
// cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 2);
// Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete
cpp11_rvalue_reference_move.MovableCopyable.movein(mo111);
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 1, 1, 3);
}
{
// null check
cpp11_rvalue_reference_move.Counter.reset_counts();
exception_thrown = false;
try {
cpp11_rvalue_reference_move.MovableCopyable.movein(null);
} catch (e) {
if (!e.message.includes("invalid null reference"))
throw new Error("incorrect exception message " + e.message);
exception_thrown = true;
}
if (!exception_thrown)
throw new Error("Should have thrown null error");
cpp11_rvalue_reference_move.Counter.check_counts(0, 0, 0, 0, 0, 0);
}
{
// output
cpp11_rvalue_reference_move.Counter.reset_counts();
var mc = cpp11_rvalue_reference_move.MovableCopyable.moveout(1234);
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1);
cpp11_rvalue_reference_move.MovableCopyable.check_numbers_match(mc, 1234);
exception_thrown = false;
try {
cpp11_rvalue_reference_move.MovableCopyable.movein(mc);
} catch (e) {
if (!e.message.includes("cannot release ownership as memory is not owned"))
throw new Error("incorrect exception message " + e.message);
exception_thrown = true;
}
if (!exception_thrown)
throw new Error("Should have thrown 'Cannot release ownership as memory is not owned' error");
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1);
}

View File

@ -1,56 +0,0 @@
require("import") -- the import fn
import("cpp11_rvalue_reference_move_input") -- import code
-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})
-- Function containing rvalue reference parameter
cpp11_rvalue_reference_move_input.Counter.reset_counts()
mo = cpp11_rvalue_reference_move_input.MovableCopyable(222)
cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 0, 0, 0)
cpp11_rvalue_reference_move_input.MovableCopyable.movein(mo)
cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2)
if not (cpp11_rvalue_reference_move_input.MovableCopyable_is_nullptr(mo)) then
error("is_nullptr failed")
end
mo = nil
cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2)
-- Move constructor test
cpp11_rvalue_reference_move_input.Counter.reset_counts()
mo = cpp11_rvalue_reference_move_input.MovableCopyable(222)
cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 0, 0, 0)
mo_moved = cpp11_rvalue_reference_move_input.MovableCopyable(mo)
cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 1)
if not (cpp11_rvalue_reference_move_input.MovableCopyable_is_nullptr(mo)) then
error("is_nullptr failed")
end
mo = nil
cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 1)
mo_moved = nil
collectgarbage() -- gc nudge needed here
cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2)
-- Move assignment operator test
cpp11_rvalue_reference_move_input.Counter.reset_counts()
mo111 = cpp11_rvalue_reference_move_input.MovableCopyable(111)
mo222 = cpp11_rvalue_reference_move_input.MovableCopyable(222)
cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 0, 0)
mo111:MoveAssign(mo222)
cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 1)
if not (cpp11_rvalue_reference_move_input.MovableCopyable_is_nullptr(mo222)) then
error("is_nullptr failed")
end
mo222 = nil
cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 1)
mo111 = nil
collectgarbage() -- gc nudge needed here
cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 2)
-- null check
cpp11_rvalue_reference_move_input.Counter.reset_counts()
s, msg = pcall(function() cpp11_rvalue_reference_move_input.MovableCopyable.movein(nil) end)
assert(s == false and msg:find("Error in MovableCopyable::movein (arg 1), expected 'MovableCopyable &&' got 'nil'", 1, true))
cpp11_rvalue_reference_move_input.Counter.check_counts(0, 0, 0, 0, 0, 0)

View File

@ -0,0 +1,66 @@
require("import") -- the import fn
import("cpp11_rvalue_reference_move") -- import code
-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})
-- Function containing rvalue reference parameter
cpp11_rvalue_reference_move.Counter.reset_counts()
mo = cpp11_rvalue_reference_move.MovableCopyable(222)
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 0, 0, 0)
cpp11_rvalue_reference_move.MovableCopyable.movein(mo)
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2)
if not (cpp11_rvalue_reference_move.MovableCopyable_is_nullptr(mo)) then
error("is_nullptr failed")
end
mo = nil
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2)
-- Move constructor test
cpp11_rvalue_reference_move.Counter.reset_counts()
mo = cpp11_rvalue_reference_move.MovableCopyable(222)
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 0, 0, 0)
mo_moved = cpp11_rvalue_reference_move.MovableCopyable(mo)
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 1)
if not (cpp11_rvalue_reference_move.MovableCopyable_is_nullptr(mo)) then
error("is_nullptr failed")
end
mo = nil
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 1)
mo_moved = nil
collectgarbage() -- gc nudge needed here
cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2)
-- Move assignment operator test
cpp11_rvalue_reference_move.Counter.reset_counts()
mo111 = cpp11_rvalue_reference_move.MovableCopyable(111)
mo222 = cpp11_rvalue_reference_move.MovableCopyable(222)
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 0, 0)
mo111:MoveAssign(mo222)
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1)
if not (cpp11_rvalue_reference_move.MovableCopyable_is_nullptr(mo222)) then
error("is_nullptr failed")
end
mo222 = nil
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1)
mo111 = nil
collectgarbage() -- gc nudge needed here
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 2)
-- null check
cpp11_rvalue_reference_move.Counter.reset_counts()
s, msg = pcall(function() cpp11_rvalue_reference_move.MovableCopyable.movein(nil) end)
assert(s == false and msg:find("Error in MovableCopyable::movein (arg 1), expected 'MovableCopyable &&' got 'nil'", 1, true))
cpp11_rvalue_reference_move.Counter.check_counts(0, 0, 0, 0, 0, 0)
-- output
cpp11_rvalue_reference_move.Counter.reset_counts()
mc = cpp11_rvalue_reference_move.MovableCopyable.moveout(1234)
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1)
cpp11_rvalue_reference_move.MovableCopyable.check_numbers_match(mc, 1234)
s, msg = pcall(function() cpp11_rvalue_reference_move.MovableCopyable.movein(mc) end)
assert(s == false and msg:find("Cannot release ownership as memory is not owned", 1, true))
cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1)

View File

@ -1,7 +1,7 @@
(load-extension "cpp11_rvalue_reference_move_input.so")
(load-extension "cpp11_rvalue_reference_move.so")
(require (lib "defmacro.ss"))
; Copied from ../schemerunme/cpp11_rvalue_reference_move_input.scm and modified for exceptions
; Copied from ../schemerunme/cpp11_rvalue_reference_move.scm and modified for exceptions
; Function containing rvalue reference parameter
(Counter-reset-counts)
@ -51,4 +51,18 @@
(error (format "incorrect exception message: ~a" exception_thrown)))
(Counter-check-counts 0 0 0 0 0 0)
; output
(Counter-reset-counts)
(define mc (MovableCopyable-moveout 1234))
(Counter-check-counts 2 0 0 0 1 1)
(MovableCopyable-check-numbers-match mc 1234)
(define exception_thrown "no exception thrown for kin")
(with-handlers ([exn:fail? (lambda (exn)
(set! exception_thrown (exn-message exn)))])
(MovableCopyable-movein mc))
(unless (string-contains? exception_thrown "cannot release ownership as memory is not owned")
(error (format "incorrect exception message: ~a" exception_thrown)))
(Counter-check-counts 2 0 0 0 1 1)
(exit 0)

View File

@ -3,7 +3,7 @@ if exist("crash_dumps_octave_core", "builtin")
crash_dumps_octave_core(0);
endif
cpp11_rvalue_reference_move_input
cpp11_rvalue_reference_move
# Function containing rvalue reference parameter
Counter.reset_counts();
@ -62,3 +62,24 @@ if (!exception_thrown)
error("Should have thrown null error");
endif
Counter.check_counts(0, 0, 0, 0, 0, 0);
# output
Counter.reset_counts();
mc = MovableCopyable.moveout(1234);
Counter.check_counts(2, 0, 0, 0, 1, 1);
MovableCopyable.check_numbers_match(mc, 1234);
exception_thrown = false;
try
MovableCopyable.movein(mc);
catch e
if (isempty(strfind(e.message, "cannot release ownership as memory is not owned")))
error("incorrect exception message: %s", e.message)
endif
exception_thrown = true;
end_try_catch
if (!exception_thrown)
error("Should have thrown 'Cannot release ownership as memory is not owned' error");
endif
Counter.check_counts(2, 0, 0, 0, 1, 1);

View File

@ -1,56 +0,0 @@
use strict;
use warnings;
use Test::More tests => 6;
BEGIN { use_ok('cpp11_rvalue_reference_move_input') }
require_ok('cpp11_rvalue_reference_move_input');
{
# Function containing rvalue reference parameter
cpp11_rvalue_reference_move_input::Counter::reset_counts();
my $mo = new cpp11_rvalue_reference_move_input::MovableCopyable(222);
cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 0, 0, 0);
cpp11_rvalue_reference_move_input::MovableCopyable::movein($mo);
cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 2);
is(cpp11_rvalue_reference_move_input::MovableCopyable::is_nullptr($mo), 1, "is_nullptr check");
undef $mo;
cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 2);
}
{
# Move constructor test
cpp11_rvalue_reference_move_input::Counter::reset_counts();
my $mo = new cpp11_rvalue_reference_move_input::MovableCopyable(222);
cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 0, 0, 0);
my $mo_moved = new cpp11_rvalue_reference_move_input::MovableCopyable($mo);
cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 1);
is(cpp11_rvalue_reference_move_input::MovableCopyable::is_nullptr($mo), 1, "is_nullptr check");
undef $mo;
cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 1);
undef $mo_moved;
cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 2);
}
{
# Move assignment operator test
cpp11_rvalue_reference_move_input::Counter::reset_counts();
my $mo111 = new cpp11_rvalue_reference_move_input::MovableCopyable(111);
my $mo222 = new cpp11_rvalue_reference_move_input::MovableCopyable(222);
cpp11_rvalue_reference_move_input::Counter::check_counts(2, 0, 0, 0, 0, 0);
$mo111->MoveAssign($mo222);
cpp11_rvalue_reference_move_input::Counter::check_counts(2, 0, 0, 0, 1, 1);
is(cpp11_rvalue_reference_move_input::MovableCopyable::is_nullptr($mo222), 1, "is_nullptr check");
undef $mo222;
cpp11_rvalue_reference_move_input::Counter::check_counts(2, 0, 0, 0, 1, 1);
undef $mo111;
cpp11_rvalue_reference_move_input::Counter::check_counts(2, 0, 0, 0, 1, 2);
}
{
# null check
cpp11_rvalue_reference_move_input::Counter::reset_counts();
eval {
cpp11_rvalue_reference_move_input::MovableCopyable::movein(undef);
};
like($@, qr/\binvalid null reference/, "Should have thrown null error");
cpp11_rvalue_reference_move_input::Counter::check_counts(0, 0, 0, 0, 0, 0);
}

View File

@ -0,0 +1,70 @@
use strict;
use warnings;
use Test::More tests => 7;
BEGIN { use_ok('cpp11_rvalue_reference_move') }
require_ok('cpp11_rvalue_reference_move');
{
# Function containing rvalue reference parameter
cpp11_rvalue_reference_move::Counter::reset_counts();
my $mo = new cpp11_rvalue_reference_move::MovableCopyable(222);
cpp11_rvalue_reference_move::Counter::check_counts(1, 0, 0, 0, 0, 0);
cpp11_rvalue_reference_move::MovableCopyable::movein($mo);
cpp11_rvalue_reference_move::Counter::check_counts(1, 0, 0, 1, 0, 2);
is(cpp11_rvalue_reference_move::MovableCopyable::is_nullptr($mo), 1, "is_nullptr check");
undef $mo;
cpp11_rvalue_reference_move::Counter::check_counts(1, 0, 0, 1, 0, 2);
}
{
# Move constructor test
cpp11_rvalue_reference_move::Counter::reset_counts();
my $mo = new cpp11_rvalue_reference_move::MovableCopyable(222);
cpp11_rvalue_reference_move::Counter::check_counts(1, 0, 0, 0, 0, 0);
my $mo_moved = new cpp11_rvalue_reference_move::MovableCopyable($mo);
cpp11_rvalue_reference_move::Counter::check_counts(1, 0, 0, 1, 0, 1);
is(cpp11_rvalue_reference_move::MovableCopyable::is_nullptr($mo), 1, "is_nullptr check");
undef $mo;
cpp11_rvalue_reference_move::Counter::check_counts(1, 0, 0, 1, 0, 1);
undef $mo_moved;
cpp11_rvalue_reference_move::Counter::check_counts(1, 0, 0, 1, 0, 2);
}
{
# Move assignment operator test
cpp11_rvalue_reference_move::Counter::reset_counts();
my $mo111 = new cpp11_rvalue_reference_move::MovableCopyable(111);
my $mo222 = new cpp11_rvalue_reference_move::MovableCopyable(222);
cpp11_rvalue_reference_move::Counter::check_counts(2, 0, 0, 0, 0, 0);
$mo111->MoveAssign($mo222);
cpp11_rvalue_reference_move::Counter::check_counts(2, 0, 0, 0, 1, 1);
is(cpp11_rvalue_reference_move::MovableCopyable::is_nullptr($mo222), 1, "is_nullptr check");
undef $mo222;
cpp11_rvalue_reference_move::Counter::check_counts(2, 0, 0, 0, 1, 1);
undef $mo111;
cpp11_rvalue_reference_move::Counter::check_counts(2, 0, 0, 0, 1, 2);
}
{
# null check
cpp11_rvalue_reference_move::Counter::reset_counts();
eval {
cpp11_rvalue_reference_move::MovableCopyable::movein(undef);
};
like($@, qr/\binvalid null reference/, "Should have thrown null error");
cpp11_rvalue_reference_move::Counter::check_counts(0, 0, 0, 0, 0, 0);
}
{
# output
cpp11_rvalue_reference_move::Counter::reset_counts();
my $mc = cpp11_rvalue_reference_move::MovableCopyable::moveout(1234);
cpp11_rvalue_reference_move::Counter::check_counts(2, 0, 0, 0, 1, 1);
cpp11_rvalue_reference_move::MovableCopyable::check_numbers_match($mc, 1234);
eval {
cpp11_rvalue_reference_move::MovableCopyable::movein($mc);
};
like($@, qr/\bcannot release ownership as memory is not owned\b/, "Should have thrown 'Cannot release ownership as memory is not owned' error");
cpp11_rvalue_reference_move::Counter::check_counts(2, 0, 0, 0, 1, 1);
}

View File

@ -61,4 +61,20 @@ try {
check::equal($exception_thrown, true, "Should have thrown null error");
Counter::check_counts(0, 0, 0, 0, 0, 0);
# output
Counter::reset_counts();
$mc = MovableCopyable::moveout(1234);
Counter::check_counts(2, 0, 0, 0, 1, 1);
MovableCopyable::check_numbers_match($mc, 1234);
$exception_thrown = false;
try {
MovableCopyable::movein($mc);
} catch (TypeError $e) {
check::str_contains($e->getMessage(), "Cannot release ownership as memory is not owned", "incorrect exception message: {$e->getMessage()}");
$exception_thrown = true;
}
check::equal($exception_thrown, true, "Should have thrown 'Cannot release ownership as memory is not owned' error");
Counter::check_counts(2, 0, 0, 0, 1, 1);
check::done();

View File

@ -1,4 +1,4 @@
from cpp11_rvalue_reference_move_input import *
from cpp11_rvalue_reference_move import *
# Function containing rvalue reference parameter
Counter.reset_counts()
@ -50,3 +50,20 @@ except ValueError as e:
if not exception_thrown:
raise RuntimeError("Should have thrown null error")
Counter.check_counts(0, 0, 0, 0, 0, 0)
# output
Counter.reset_counts()
mc = MovableCopyable.moveout(1234)
Counter.check_counts(2, 0, 0, 0, 1, 1)
MovableCopyable.check_numbers_match(mc, 1234)
exception_thrown = False
try:
MovableCopyable.movein(mc)
except RuntimeError as e:
if "cannot release ownership as memory is not owned" not in str(e):
raise RuntimeError("incorrect exception message:" + str(e))
exception_thrown = True
if not exception_thrown:
raise RuntimeError("Should have thrown 'Cannot release ownership as memory is not owned' error")
Counter.check_counts(2, 0, 0, 0, 1, 1)

View File

@ -4,25 +4,24 @@ a = cpp11_rvalue_reference.A()
a.setAcopy(5)
if a.getAcopy() != 5:
raise RunTimeError("int A::getAcopy() value is ",
raise RuntimeError("int A::getAcopy() value is ",
a.getAcopy(), " should be 5")
ptr = a.getAptr()
a.setAptr(ptr)
if a.getAcopy() != 5:
raise RunTimeError("after A::setAptr(): int A::getAcopy() value is ", a.getAcopy(
raise RuntimeError("after A::setAptr(): int A::getAcopy() value is ", a.getAcopy(
), " should be 5")
a.setAref(ptr)
if a.getAcopy() != 5:
raise RunTimeError("after A::setAref(): int A::getAcopy() value is ", a.getAcopy(
raise RuntimeError("after A::setAref(): int A::getAcopy() value is ", a.getAcopy(
), " should be 5")
rvalueref = a.getAmove()
# WIP: out rvalue references not yet modified for taking ownership
# a.setAmove(rvalueref)
# if a.getAcopy() != 5:
# raise RunTimeError("after A::setAmove(): int A::getAcopy() value is ", a.getAcopy(
# ), " should be 5")
a.setAref(rvalueref)
if a.getAcopy() != 5:
raise RuntimeError("after A::setAmove(): int A::getAcopy() value is ", a.getAcopy(
), " should be 5")

View File

@ -1,87 +0,0 @@
#!/usr/bin/env ruby
require 'swig_assert'
require 'cpp11_rvalue_reference_move_input'
# Function containing rvalue reference parameter
Cpp11_rvalue_reference_move_input::Counter.reset_counts()
mo = Cpp11_rvalue_reference_move_input::MovableCopyable.new(222)
Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 0, 0, 0)
Cpp11_rvalue_reference_move_input::MovableCopyable.movein(mo)
Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 2)
exception_thrown = false
begin
Cpp11_rvalue_reference_move_input::MovableCopyable.is_nullptr(mo)
rescue ObjectPreviouslyDeleted
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "is_nullptr failed to throw"
end
mo = nil
Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 2)
# Move constructor test
Cpp11_rvalue_reference_move_input::Counter.reset_counts()
mo = Cpp11_rvalue_reference_move_input::MovableCopyable.new(222)
Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 0, 0, 0)
mo_moved = Cpp11_rvalue_reference_move_input::MovableCopyable.new(mo)
Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 1)
exception_thrown = false
begin
Cpp11_rvalue_reference_move_input::MovableCopyable.is_nullptr(mo)
rescue ObjectPreviouslyDeleted
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "is_nullptr failed to throw"
end
mo = nil
Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 1)
# mo_moved = nil
# Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 2)
# Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete
Cpp11_rvalue_reference_move_input::MovableCopyable.movein(mo_moved)
Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 2, 0, 3)
# Move assignment operator test
Cpp11_rvalue_reference_move_input::Counter.reset_counts()
mo111 = Cpp11_rvalue_reference_move_input::MovableCopyable.new(111)
mo222 = Cpp11_rvalue_reference_move_input::MovableCopyable.new(222)
Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 0, 0, 0)
mo111.MoveAssign(mo222)
Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 0, 1, 1)
exception_thrown = false
begin
Cpp11_rvalue_reference_move_input::MovableCopyable.is_nullptr(mo222)
rescue ObjectPreviouslyDeleted
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "is_nullptr failed to throw"
end
mo222 = nil
Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 0, 1, 1)
# mo111 = nil
# Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 0, 1, 2)
# Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete
Cpp11_rvalue_reference_move_input::MovableCopyable.movein(mo111)
Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 1, 1, 3)
# null check
Cpp11_rvalue_reference_move_input::Counter.reset_counts()
exception_thrown = false
begin
Cpp11_rvalue_reference_move_input::MovableCopyable.movein(nil)
rescue ArgumentError => e
if (!e.to_s.include? "invalid null reference")
raise RuntimeError, "incorrect exception message: #{e.to_s}"
end
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "Should have thrown null error"
end
Cpp11_rvalue_reference_move_input::Counter.check_counts(0, 0, 0, 0, 0, 0)

View File

@ -0,0 +1,106 @@
#!/usr/bin/env ruby
require 'swig_assert'
require 'cpp11_rvalue_reference_move'
# Function containing rvalue reference parameter
Cpp11_rvalue_reference_move::Counter.reset_counts()
mo = Cpp11_rvalue_reference_move::MovableCopyable.new(222)
Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 0, 0, 0)
Cpp11_rvalue_reference_move::MovableCopyable.movein(mo)
Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 1, 0, 2)
exception_thrown = false
begin
Cpp11_rvalue_reference_move::MovableCopyable.is_nullptr(mo)
rescue ObjectPreviouslyDeleted
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "is_nullptr failed to throw"
end
mo = nil
Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 1, 0, 2)
# Move constructor test
Cpp11_rvalue_reference_move::Counter.reset_counts()
mo = Cpp11_rvalue_reference_move::MovableCopyable.new(222)
Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 0, 0, 0)
mo_moved = Cpp11_rvalue_reference_move::MovableCopyable.new(mo)
Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 1, 0, 1)
exception_thrown = false
begin
Cpp11_rvalue_reference_move::MovableCopyable.is_nullptr(mo)
rescue ObjectPreviouslyDeleted
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "is_nullptr failed to throw"
end
mo = nil
Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 1, 0, 1)
# mo_moved = nil
# Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 1, 0, 2)
# Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete
Cpp11_rvalue_reference_move::MovableCopyable.movein(mo_moved)
Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 2, 0, 3)
# Move assignment operator test
Cpp11_rvalue_reference_move::Counter.reset_counts()
mo111 = Cpp11_rvalue_reference_move::MovableCopyable.new(111)
mo222 = Cpp11_rvalue_reference_move::MovableCopyable.new(222)
Cpp11_rvalue_reference_move::Counter.check_counts(2, 0, 0, 0, 0, 0)
mo111.MoveAssign(mo222)
Cpp11_rvalue_reference_move::Counter.check_counts(2, 0, 0, 0, 1, 1)
exception_thrown = false
begin
Cpp11_rvalue_reference_move::MovableCopyable.is_nullptr(mo222)
rescue ObjectPreviouslyDeleted
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "is_nullptr failed to throw"
end
mo222 = nil
Cpp11_rvalue_reference_move::Counter.check_counts(2, 0, 0, 0, 1, 1)
# mo111 = nil
# Cpp11_rvalue_reference_move::Counter.check_counts(2, 0, 0, 0, 1, 2)
# Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete
Cpp11_rvalue_reference_move::MovableCopyable.movein(mo111)
Cpp11_rvalue_reference_move::Counter.check_counts(2, 0, 0, 1, 1, 3)
# null check
Cpp11_rvalue_reference_move::Counter.reset_counts()
exception_thrown = false
begin
Cpp11_rvalue_reference_move::MovableCopyable.movein(nil)
rescue ArgumentError => e
if (!e.to_s.include? "invalid null reference")
raise RuntimeError, "incorrect exception message: #{e.to_s}"
end
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "Should have thrown null error"
end
Cpp11_rvalue_reference_move::Counter.check_counts(0, 0, 0, 0, 0, 0)
# output
Cpp11_rvalue_reference_move::Counter.reset_counts()
mc = Cpp11_rvalue_reference_move::MovableCopyable.moveout(1234)
Cpp11_rvalue_reference_move::Counter.check_counts(2, 0, 0, 0, 1, 1)
Cpp11_rvalue_reference_move::MovableCopyable.check_numbers_match(mc, 1234)
exception_thrown = false
begin
Cpp11_rvalue_reference_move::MovableCopyable.movein(mc)
rescue RuntimeError => e
if (!e.to_s.include? "cannot release ownership as memory is not owned")
raise RuntimeError, "incorrect exception message: #{e.to_s}"
end
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "Should have thrown 'Cannot release ownership as memory is not owned' error"
end
Cpp11_rvalue_reference_move::Counter.check_counts(2, 0, 0, 0, 1, 1)

View File

@ -43,4 +43,15 @@
; TODO: check the exception message
(Counter-check-counts 0 0 0 0 0 0)
; output
(Counter-reset-counts)
(define mc (MovableCopyable-moveout 1234))
(Counter-check-counts 2 0 0 0 1 1)
(MovableCopyable-check-numbers-match mc 1234)
(expect-throw 'misc-error
(MovableCopyable-movein mc))
; TODO: check the exception message
(Counter-check-counts 2 0 0 0 1 1)
(exit 0)

View File

@ -1,5 +1,5 @@
if [ catch { load ./cpp11_rvalue_reference_move_input[info sharedlibextension] cpp11_rvalue_reference_move_input} err_msg ] {
if [ catch { load ./cpp11_rvalue_reference_move[info sharedlibextension] cpp11_rvalue_reference_move} err_msg ] {
puts stderr "Could not load shared object:\n$err_msg"
}
@ -60,3 +60,23 @@ if {!$exception_thrown} {
error "Should have thrown null error"
}
Counter_check_counts 0 0 0 0 0 0
# output
Counter_reset_counts
set mc [MovableCopyable_moveout 1234]
Counter_check_counts 2 0 0 0 1 1
MovableCopyable_check_numbers_match $mc 1234
set exception_thrown 0
if [ catch {
MovableCopyable_movein $mc
} e ] {
if {[string first "cannot release ownership as memory is not owned" $e] == -1} {
error "incorrect exception message: $e"
}
set exception_thrown 1
}
if {!$exception_thrown} {
error "Should have thrown 'Cannot release ownership as memory is not owned' error"
}
Counter_check_counts 2 0 0 0 1 1