diff options
author | William S Fulton <wsf@fultondesigns.co.uk> | 2022-08-31 22:28:18 +0100 |
---|---|---|
committer | William S Fulton <wsf@fultondesigns.co.uk> | 2022-09-02 08:24:30 +0100 |
commit | 0b1d3e3e868514c9cd0674839ed94fbff5653a21 (patch) | |
tree | 0df4ab53b1c4288b84b43f804699ae205a5ce0ed /Doc | |
parent | 7934561874b4f5da4061c62b0c28f6dd35ed05ae (diff) | |
download | swig-0b1d3e3e868514c9cd0674839ed94fbff5653a21.tar.gz |
Docs on rvalue parameter changes
Diffstat (limited to 'Doc')
-rw-r--r-- | Doc/Manual/CPlusPlus11.html | 63 |
1 files changed, 60 insertions, 3 deletions
diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index 7618b6dbe..ca8d3d575 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -98,6 +98,7 @@ class MyClass { ... std::vector<int> numbers; public: + MyClass() : numbers() {} MyClass(MyClass &&other) : numbers(std::move(other.numbers)) {} MyClass & operator=(MyClass &&other) { numbers = std::move(other.numbers); @@ -107,8 +108,8 @@ public: </pre></div> <p> -Rvalue references are designed for C++ temporaries and so are not very useful when used from non-C++ target languages. -Generally you would just ignore them via <tt>%ignore</tt> before parsing the class. +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. For example, ignore the move constructor: </p> @@ -117,7 +118,39 @@ For example, ignore the move constructor: </pre></div> <p> -The plan is to ignore move constructors by default in a future version of SWIG. Note that both normal assignment operators as well as move assignment operators are ignored by default in most target languages with the following warning: +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'. +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> + +<p> +In this way, the SWIG proxy class works much like an exclusively owned smart pointer (think of <tt>std::unique_ptr</tt>), passing ownership to the called C++ function/constructor. +Let's consider an example in Java using the wrapped proxy class from above: +</p> + +<div class="targetlang"><pre> +MyClass mc = new MyClass(); +MyClass mc1 = new MyClass(mc); // move constructor +MyClass mc2 = new MyClass(mc); // move constructor fails +</pre></div> + +<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: +</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) +</pre> +</div> + + +<p> +Note that both normal copy assignment operators as well as move assignment operators are ignored by default in the target languages with the following warning: </p> <div class="shell"> @@ -126,6 +159,30 @@ example.i:18: Warning 503: Can't wrap 'operator =' unless renamed to a valid ide </pre> </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: +</p> +<div class="code"><pre> +%rename(MoveAssign) MyClass::operator=(MyClass &&); +</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: +</p> + +<div class="targetlang"><pre> +MyClass mc = new MyClass(); +MyClass mc2 = mc.MoveAssign(mc); +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. +</p> + <H4><a name="CPlusPlus11_move_only">7.2.1.1 Movable and move-only types</a></H4> |