mirror of https://github.com/swig/swig
Add std::unique_ptr && output typemaps
Move semantics are not supported by default. They behave as if a lvalue reference was returned.
This commit is contained in:
parent
e76952e355
commit
3f1e40d2f4
|
@ -12,7 +12,8 @@ Version 4.3.0 (in progress)
|
|||
|
||||
2024-02-02: wsfulton
|
||||
#2650 Add support for movable std::unique_ptr by adding in std::unique_ptr &&
|
||||
typemaps.
|
||||
input typemaps. The std::unique && output typemaps do not support move
|
||||
semantics by default and behave like lvalue references.
|
||||
|
||||
2024-01-23: wsfulton
|
||||
Add missing use of move constructor instead of copy constructor when
|
||||
|
|
|
@ -2221,6 +2221,19 @@ void grab(std::unique_ptr<Klass> &&);
|
|||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Move semantics are not provided when wrapping a C++ function that returns a <tt>std::unique_ptr</tt> by rvalue reference.
|
||||
The target language proxy class wrapper that is returned does not own the underlying C++ object.
|
||||
Example:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
std::unique_ptr<Klass> && RvalueRefReturn();
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
|
||||
<p>
|
||||
<b>Compatibility note:</b> Support for <tt>std::unique_ptr</tt> was first added in SWIG-4.1.0.
|
||||
This initial support contained the move semantics when passing a <tt>std::unique_ptr</tt> around by value. Support for passing a <tt>std::unique_ptr</tt> around by rvalue reference was added in SWIG-4.3.0.
|
||||
|
|
|
@ -98,6 +98,26 @@ std::unique_ptr<Klass> makeNullUniquePtr() {
|
|||
return std::unique_ptr<Klass>();
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
std::unique_ptr<Klass>&& makeRVRKlassUniquePtr(const char* label) {
|
||||
static std::unique_ptr<Klass> up;
|
||||
#if !defined(SWIGTCL)
|
||||
up.reset(label ? new Klass(label) : nullptr);
|
||||
#else // No way to pass a null pointer for a string as "NULL" is only way for Tcl to specify a null pointer
|
||||
up.reset(strcmp(label, "NULL") != 0 ? new Klass(label) : nullptr);
|
||||
#endif
|
||||
return std::move(up);
|
||||
}
|
||||
|
||||
/*
|
||||
std::unique_ptr<Klass>& makeRefKlassUniquePtr(const char* label) {
|
||||
static std::unique_ptr<Klass> up;
|
||||
up.reset(new Klass(label));
|
||||
return up;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
int overloadTest() {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -204,5 +204,13 @@ public class cpp11_std_unique_ptr_runme {
|
|||
|
||||
if (cpp11_std_unique_ptr.makeNullUniquePtr() != null)
|
||||
throw new Exception("null failure");
|
||||
|
||||
// unique_ptr as output (rvalue ref)
|
||||
k1 = cpp11_std_unique_ptr.makeRVRKlassUniquePtr("first");
|
||||
if (k1.getLabel() != "first")
|
||||
throw new Exception("wrong object label");
|
||||
k1 = cpp11_std_unique_ptr.makeRVRKlassUniquePtr(null);
|
||||
if (k1 != null)
|
||||
throw new Exception("not null");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -200,4 +200,12 @@ void main() {
|
|||
|
||||
if (makeNullUniquePtr() !is null)
|
||||
throw new Exception("null failure");
|
||||
|
||||
// unique_ptr as output (rvalue ref)
|
||||
k1 = makeRVRKlassUniquePtr("first");
|
||||
if (k1.getLabel() != "first")
|
||||
throw new Exception("wrong object label");
|
||||
k1 = makeRVRKlassUniquePtr(null);
|
||||
if (k1 !is null)
|
||||
throw new Exception("not null");
|
||||
}
|
||||
|
|
|
@ -228,5 +228,13 @@ public class cpp11_std_unique_ptr_runme {
|
|||
|
||||
if (cpp11_std_unique_ptr.makeNullUniquePtr() != null)
|
||||
throw new RuntimeException("null failure");
|
||||
|
||||
// unique_ptr as output (rvalue ref)
|
||||
k1 = cpp11_std_unique_ptr.makeRVRKlassUniquePtr("first");
|
||||
if (!k1.getLabel().equals("first"))
|
||||
throw new RuntimeException("wrong object label");
|
||||
k1 = cpp11_std_unique_ptr.makeRVRKlassUniquePtr(null);
|
||||
if (k1 != null)
|
||||
throw new RuntimeException("not null");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -213,3 +213,9 @@ checkCount(0);
|
|||
|
||||
if (cpp11_std_unique_ptr.makeNullUniquePtr() != null)
|
||||
throw new Error("null failure");
|
||||
|
||||
// unique_ptr as output (rvalue ref)
|
||||
k1 = cpp11_std_unique_ptr.makeRVRKlassUniquePtr("first");
|
||||
if (k1.getLabel() !== "first")
|
||||
throw new Error("wrong object label");
|
||||
k1 = cpp11_std_unique_ptr.makeRVRKlassUniquePtr(null);
|
||||
|
|
|
@ -180,3 +180,10 @@ k2 = nil
|
|||
checkCount(0)
|
||||
|
||||
assert(cpp11_std_unique_ptr.makeNullUniquePtr() == nil)
|
||||
|
||||
-- unique_ptr as output (rvalue ref)
|
||||
k1 = cpp11_std_unique_ptr.makeRVRKlassUniquePtr("first")
|
||||
if not (k1:getLabel() == "first") then
|
||||
error("wrong object label")
|
||||
end
|
||||
assert(cpp11_std_unique_ptr.makeRVRKlassUniquePtr(nil) == nil)
|
||||
|
|
|
@ -176,4 +176,11 @@
|
|||
(unless (null? (makeNullUniquePtr))
|
||||
(error "null failure"))
|
||||
|
||||
; unique_ptr as output (rvalue ref)
|
||||
(define k1 (makeRVRKlassUniquePtr "first"))
|
||||
(unless (string=? (Klass-getLabel k1) "first")
|
||||
(error "wrong object label" ))
|
||||
(unless (null? (makeRVRKlassUniquePtr '()))
|
||||
(error "null failure"))
|
||||
|
||||
(exit 0)
|
||||
|
|
|
@ -228,3 +228,11 @@ null_smart_prt = makeNullUniquePtr();
|
|||
assert(ismatrix(null_smart_prt))
|
||||
assert(size(null_smart_prt) == size([]))
|
||||
assert(isequal([], null_smart_prt))
|
||||
|
||||
# unique_ptr as output (rvalue ref)
|
||||
k1 = makeRVRKlassUniquePtr("first");
|
||||
if (!strcmp(k1.getLabel(), "first"))
|
||||
error("wrong object label");
|
||||
endif
|
||||
k1 = makeRVRKlassUniquePtr([]);
|
||||
assert(isequal([], k1))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 58;
|
||||
use Test::More tests => 60;
|
||||
BEGIN { use_ok('cpp11_std_unique_ptr') }
|
||||
require_ok('cpp11_std_unique_ptr');
|
||||
|
||||
|
@ -161,3 +161,8 @@ undef $k2;
|
|||
checkCount(0);
|
||||
|
||||
is(cpp11_std_unique_ptr::makeNullUniquePtr(), undef);
|
||||
|
||||
# unique_ptr as output (rvalue ref)
|
||||
my $k1 = cpp11_std_unique_ptr::makeRVRKlassUniquePtr("first");
|
||||
is($k1->getLabel, "first", "proper label");
|
||||
is(cpp11_std_unique_ptr::makeRVRKlassUniquePtr(undef), undef);
|
||||
|
|
|
@ -181,4 +181,10 @@ checkCount(0);
|
|||
|
||||
check::equal(makeNullUniquePtr(), NULL);
|
||||
|
||||
# unique_ptr as output (rvalue ref)
|
||||
$k1 = makeRVRKlassUniquePtr("first");
|
||||
check::equal($k1->getLabel(), "first", "proper label");
|
||||
$k1 = makeRVRKlassUniquePtr(NULL);
|
||||
check::equal(makeRVRKlassUniquePtr(NULL), NULL);
|
||||
|
||||
check::done();
|
||||
|
|
|
@ -185,3 +185,10 @@ checkCount(0)
|
|||
|
||||
if (makeNullUniquePtr() != None):
|
||||
raise RuntimeError("null failure")
|
||||
|
||||
# unique_ptr as output (rvalue ref)
|
||||
k1 = makeRVRKlassUniquePtr("first")
|
||||
if k1.getLabel() != "first":
|
||||
raise "wrong object label"
|
||||
if (makeRVRKlassUniquePtr(None) != None):
|
||||
raise RuntimeError("null failure")
|
||||
|
|
|
@ -254,3 +254,8 @@ k2 = nil
|
|||
gc_check(0)
|
||||
|
||||
swig_assert_equal_simple(Cpp11_std_unique_ptr::makeNullUniquePtr(), nil)
|
||||
|
||||
# unique_ptr as output (rvalue ref)
|
||||
k1 = Cpp11_std_unique_ptr::makeRVRKlassUniquePtr("first")
|
||||
swig_assert_equal_simple(k1.getLabel(), "first")
|
||||
swig_assert_equal_simple(Cpp11_std_unique_ptr::makeRVRKlassUniquePtr(nil), nil)
|
||||
|
|
|
@ -254,3 +254,12 @@ checkCount 0
|
|||
if {[makeNullUniquePtr] != "NULL"} {
|
||||
error "null failure"
|
||||
}
|
||||
|
||||
# unique_ptr as output (rvalue ref)
|
||||
set k1 [makeRVRKlassUniquePtr "first"]
|
||||
if {[$k1 getLabel] != "first"} {
|
||||
error "wrong object label"
|
||||
}
|
||||
if {[makeRVRKlassUniquePtr "NULL"] != "NULL"} {
|
||||
error "null failure"
|
||||
}
|
||||
|
|
|
@ -24,12 +24,22 @@
|
|||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
$result = (void *)$1.release();
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
$result = (void *)$1->get();
|
||||
%}
|
||||
|
||||
|
||||
%typemap(csout, excode=SWIGEXCODE) std::unique_ptr< TYPE > {
|
||||
System.IntPtr cPtr = $imcall;
|
||||
$typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, true);$excode
|
||||
return ret;
|
||||
}
|
||||
%typemap(csout, excode=SWIGEXCODE) std::unique_ptr< TYPE > && {
|
||||
System.IntPtr cPtr = $imcall;
|
||||
$typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, false);$excode
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && ""
|
||||
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
$result = (void *)$1.release();
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
$result = (void *)$1->get();
|
||||
%}
|
||||
|
||||
|
||||
%typemap(dout, excode=SWIGEXCODE,
|
||||
nativepointer="{\n auto ret = cast($dtype)$imcall;$excode\n return ret;\n}"
|
||||
|
@ -34,6 +38,14 @@
|
|||
$typemap(dtype, TYPE) ret = (cPtr is null) ? null : new $typemap(dtype, TYPE)(cPtr, true);$excode
|
||||
return ret;
|
||||
}
|
||||
%typemap(dout, excode=SWIGEXCODE,
|
||||
nativepointer="{\n auto ret = cast($dtype)$imcall;$excode\n return ret;\n}"
|
||||
) std::unique_ptr< TYPE > && {
|
||||
void* cPtr = $imcall;
|
||||
$typemap(dtype, TYPE) ret = (cPtr is null) ? null : new $typemap(dtype, TYPE)(cPtr, false);$excode
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && ""
|
||||
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN));
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
%set_output(SWIG_NewPointerObj($1->get(), $descriptor(TYPE *), $owner));
|
||||
%}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && {
|
||||
void *vptr = 0;
|
||||
|
|
|
@ -28,11 +28,21 @@
|
|||
*(TYPE **) &lpp = $1.release();
|
||||
$result = lpp;
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
jlong lpp = 0;
|
||||
*(TYPE **) &lpp = $1->get();
|
||||
$result = lpp;
|
||||
%}
|
||||
|
||||
|
||||
%typemap(javaout) std::unique_ptr< TYPE > {
|
||||
long cPtr = $jnicall;
|
||||
return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
|
||||
}
|
||||
%typemap(javaout) std::unique_ptr< TYPE > && {
|
||||
long cPtr = $jnicall;
|
||||
return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, false);
|
||||
}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && ""
|
||||
|
||||
|
|
|
@ -34,9 +34,25 @@
|
|||
$1 = &uptr;
|
||||
}
|
||||
|
||||
%typemap(in, noblock=1) std::unique_ptr< TYPE > && (void *argp = 0, int res = 0, std::unique_ptr< TYPE > uptr) {
|
||||
res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
|
||||
if (!SWIG_IsOK(res)) {
|
||||
if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
|
||||
%releasenotowned_fail(res, "TYPE *", $symname, $argnum);
|
||||
} else {
|
||||
%argument_fail(res, "TYPE *", $symname, $argnum);
|
||||
}
|
||||
}
|
||||
uptr.reset((TYPE *)argp);
|
||||
$1 = &uptr;
|
||||
}
|
||||
|
||||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
%set_output(SWIG_NewPointerObj($1->get(), $descriptor(TYPE *), $owner | %newpointer_flags));
|
||||
%}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && {
|
||||
void *vptr = 0;
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
%set_output(SWIG_NewPointerObj($1->get(), $descriptor(TYPE *), $owner | %newpointer_flags));
|
||||
%}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && {
|
||||
void *vptr = 0;
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
%set_output(SWIG_NewPointerObj($1->get(), $descriptor(TYPE *), $owner | %newpointer_flags));
|
||||
%}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && {
|
||||
void *vptr = 0;
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
SWIG_NewPointerObj(L, $1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); SWIG_arg++;
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
SWIG_NewPointerObj(L, $1->get(), $descriptor(TYPE *), $owner); SWIG_arg++;
|
||||
%}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && {
|
||||
void *vptr = 0;
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN));
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
%set_output(SWIG_NewPointerObj($1->get(), $descriptor(TYPE *), $owner));
|
||||
%}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && {
|
||||
void *vptr = 0;
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
%set_output(SWIG_NewPointerObj($1->get(), $descriptor(TYPE *), $owner | %newpointer_flags));
|
||||
%}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && {
|
||||
void *vptr = 0;
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
%set_output(SWIG_NewPointerObj($1->get(), $descriptor(TYPE *), $owner | %newpointer_flags));
|
||||
%}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && {
|
||||
void *vptr = 0;
|
||||
|
|
|
@ -41,6 +41,9 @@
|
|||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
SWIG_SetPointerZval($result, (void *)$1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN);
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
SWIG_SetPointerZval($result, (void *)$1->get(), $descriptor(TYPE *), $owner);
|
||||
%}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && {
|
||||
void *vptr = 0;
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
%set_output(SWIG_NewPointerObj($1->get(), $descriptor(TYPE *), $owner | %newpointer_flags));
|
||||
%}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && {
|
||||
void *vptr = 0;
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
%set_output(SWIG_NewPointerObj($1->get(), $descriptor(TYPE *), $owner | %newpointer_flags));
|
||||
%}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && {
|
||||
void *vptr = 0;
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
%typemap (out) std::unique_ptr< TYPE > %{
|
||||
Tcl_SetObjResult(interp, SWIG_NewInstanceObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN));
|
||||
%}
|
||||
%typemap (out) std::unique_ptr< TYPE > && %{
|
||||
Tcl_SetObjResult(interp, SWIG_NewInstanceObj($1->get(), $descriptor(TYPE *), $owner));
|
||||
%}
|
||||
|
||||
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > && {
|
||||
void *vptr = 0;
|
||||
|
|
Loading…
Reference in New Issue