C++11 rvalue reference docs updated.
This commit is contained in:
parent
7a96fba836
commit
5f7f8f17eb
1 changed files with 55 additions and 26 deletions
|
|
@ -62,12 +62,15 @@
|
||||||
|
|
||||||
<p>This chapter gives you a brief overview about the SWIG
|
<p>This chapter gives you a brief overview about the SWIG
|
||||||
implementation of the C++11 standard. This part of SWIG is still a work in
|
implementation of the C++11 standard. This part of SWIG is still a work in
|
||||||
progress. Initial C++11 support for SWIG was written during the
|
progress.
|
||||||
Google Summer of Code 2009 period.</p>
|
</p>
|
||||||
<p>SWIG supports all the new C++ syntax changes with some minor limitations
|
<p>SWIG supports the new C++ syntax changes with some minor limitations
|
||||||
(decltype expressions, variadic templates number). Wrappers for the
|
(decltype expressions, variadic templates number). Wrappers for the
|
||||||
new STL types (unordered_ containers, result_of, tuples) are not supported
|
new STL types (unordered_ containers, result_of, tuples) are incomplete.
|
||||||
yet.</p>
|
The wrappers for the new containers would work much like the C++03 containers and
|
||||||
|
users are welcome to help by adapting the existing container interface files and submitting them
|
||||||
|
as a patch for inclusion in future versions of SWIG.
|
||||||
|
</p>
|
||||||
|
|
||||||
<H2><a name="CPlusPlus11_core_language_changes"></a>7.2 Core language changes</H2>
|
<H2><a name="CPlusPlus11_core_language_changes"></a>7.2 Core language changes</H2>
|
||||||
|
|
||||||
|
|
@ -75,19 +78,45 @@ yet.</p>
|
||||||
<H3><a name="CPlusPlus11_rvalue_reference_and_move_semantics"></a>7.2.1 Rvalue reference and move semantics</H3>
|
<H3><a name="CPlusPlus11_rvalue_reference_and_move_semantics"></a>7.2.1 Rvalue reference and move semantics</H3>
|
||||||
|
|
||||||
|
|
||||||
<p>SWIG correctly parses the new operator && the same as the reference operator &.</p>
|
<p>
|
||||||
|
SWIG correctly parses the rvalue reference syntax '&&',
|
||||||
|
for example the typical usage of it in the move constructor and move assignment operator below:
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>The wrapper for the following code is correctly produced:</p>
|
|
||||||
<div class="code"><pre>
|
<div class="code"><pre>
|
||||||
class MyClass {
|
class MyClass {
|
||||||
MyClass(MyClass&& p) : ptr(p.ptr) {p.ptr = 0;}
|
...
|
||||||
MyClass& operator=(MyClass&& p) {
|
std::vector<int> numbers;
|
||||||
std::swap(ptr, p.ptr);
|
public:
|
||||||
|
MyClass(MyClass &&other) : numbers(std::move(other.numbers)) {}
|
||||||
|
MyClass & operator=(MyClass &&other) {
|
||||||
|
numbers = std::move(other.numbers);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</pre></div>
|
</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.
|
||||||
|
For example, ignore the move constructor:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code"><pre>
|
||||||
|
%ignore MyClass::MyClass(MyClass &&);
|
||||||
|
</pre></div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The plan is to ignore them 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:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="shell">
|
||||||
|
<pre>
|
||||||
|
example.i:18: Warning 503: Can't wrap 'operator =' unless renamed to a valid identifier.
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<H3><a name="CPlusPlus11_generalized_constant_expressions"></a>7.2.2 Generalized constant expressions</H3>
|
<H3><a name="CPlusPlus11_generalized_constant_expressions"></a>7.2.2 Generalized constant expressions</H3>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -387,7 +416,7 @@ public:
|
||||||
int b;
|
int b;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
A() : A( 10 ) {}
|
A() : A(10) {}
|
||||||
A(int aa) : A(aa, 20) {}
|
A(int aa) : A(aa, 20) {}
|
||||||
A(int aa, int bb) : A(aa, bb, 30) {}
|
A(int aa, int bb) : A(aa, bb, 30) {}
|
||||||
A(int aa, int bb, int cc) { a=aa; b=bb; c=cc; }
|
A(int aa, int bb, int cc) { a=aa; b=bb; c=cc; }
|
||||||
|
|
@ -524,9 +553,9 @@ public:
|
||||||
class TestClass {
|
class TestClass {
|
||||||
public:
|
public:
|
||||||
//implicit converting constructor
|
//implicit converting constructor
|
||||||
TestClass( U const &val ) { t=val.u; }
|
TestClass(U const &val) { t=val.u; }
|
||||||
// explicit constructor
|
// explicit constructor
|
||||||
explicit TestClass( V const &val ) { t=val.v; }
|
explicit TestClass(V const &val) { t=val.v; }
|
||||||
|
|
||||||
int t;
|
int t;
|
||||||
};
|
};
|
||||||
|
|
@ -629,7 +658,7 @@ initializers) with some limitations. The following code is correctly parsed:</p>
|
||||||
<div class="code"><pre>
|
<div class="code"><pre>
|
||||||
template <typename... BaseClasses> class ClassName : public BaseClasses... {
|
template <typename... BaseClasses> class ClassName : public BaseClasses... {
|
||||||
public:
|
public:
|
||||||
ClassName (BaseClasses&&... baseClasses) : BaseClasses(baseClasses)... {}
|
ClassName (BaseClasses &&... baseClasses) : BaseClasses(baseClasses)... {}
|
||||||
}
|
}
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
|
|
@ -773,8 +802,8 @@ For example:</p>
|
||||||
|
|
||||||
<div class="code"><pre>
|
<div class="code"><pre>
|
||||||
struct NonCopyable {
|
struct NonCopyable {
|
||||||
NonCopyable& operator=(const NonCopyable&) = delete; /* Removes operator= */
|
NonCopyable & operator=(const NonCopyable &) = delete; /* Removes operator= */
|
||||||
NonCopyable(const NonCopyable&) = delete; /* Removed copy constructor */
|
NonCopyable(const NonCopyable &) = delete; /* Removed copy constructor */
|
||||||
NonCopyable() = default; /* Explicitly allows the empty constructor */
|
NonCopyable() = default; /* Explicitly allows the empty constructor */
|
||||||
void *operator new(std::size_t) = delete; /* Removes new NonCopyable */
|
void *operator new(std::size_t) = delete; /* Removes new NonCopyable */
|
||||||
};
|
};
|
||||||
|
|
@ -881,19 +910,19 @@ There is no special smart pointer handling available for <tt>std::weak_ptr</tt>
|
||||||
<p>The new ref and cref classes are used to instantiate a parameter as a reference of a template function. For example:</p>
|
<p>The new ref and cref classes are used to instantiate a parameter as a reference of a template function. For example:</p>
|
||||||
|
|
||||||
<div class="code"><pre>
|
<div class="code"><pre>
|
||||||
void f( int &r ) { r++; }
|
void f(int &r) { r++; }
|
||||||
|
|
||||||
// Template function.
|
// Template function.
|
||||||
template< class F, class P > void g( F f, P t ) { f(t); }
|
template< class F, class P > void g(F f, P t) { f(t); }
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
int i = 0 ;
|
int i = 0 ;
|
||||||
g( f, i ) ; // 'g<void ( int &r ), int>' is instantiated
|
g(f, i) ; // 'g<void (int &r), int>' is instantiated
|
||||||
// then 'i' will not be modified.
|
// then 'i' will not be modified.
|
||||||
cout << i << endl ; // Output -> 0
|
cout << i << endl ; // Output -> 0
|
||||||
|
|
||||||
g( f, ref(i) ) ; // 'g<void(int &r),reference_wrapper<int>>' is instantiated
|
g(f, ref(i)) ; // 'g<void(int &r),reference_wrapper<int>>' is instantiated
|
||||||
// then 'i' will be modified.
|
// then 'i' will be modified.
|
||||||
cout << i << endl ; // Output -> 1
|
cout << i << endl ; // Output -> 1
|
||||||
}
|
}
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
@ -939,17 +968,17 @@ b = t(1,2) # invoke C++ function object
|
||||||
<div class="code"><pre>
|
<div class="code"><pre>
|
||||||
// First way of operating.
|
// First way of operating.
|
||||||
template< bool B > struct algorithm {
|
template< bool B > struct algorithm {
|
||||||
template< class T1, class T2 > int do_it( T1&, T2& ) { /*...*/ }
|
template< class T1, class T2 > int do_it(T1 &, T2 &) { /*...*/ }
|
||||||
};
|
};
|
||||||
// Second way of operating.
|
// Second way of operating.
|
||||||
template<> struct algorithm<true> {
|
template<> struct algorithm<true> {
|
||||||
template< class T1, class T2 > int do_it( T1, T2 ) { /*...*/ }
|
template< class T1, class T2 > int do_it(T1, T2) { /*...*/ }
|
||||||
};
|
};
|
||||||
// Instantiating 'elaborate' will automatically instantiate the correct way to operate.
|
// Instantiating 'elaborate' will automatically instantiate the correct way to operate.
|
||||||
template< class T1, class T2 > int elaborate( T1 A, T2 B ) {
|
template< class T1, class T2 > int elaborate(T1 A, T2 B) {
|
||||||
// Use the second way only if 'T1' is an integer and if 'T2' is
|
// Use the second way only if 'T1' is an integer and if 'T2' is
|
||||||
// in floating point, otherwise use the first way.
|
// in floating point, otherwise use the first way.
|
||||||
return algorithm< is_integral<T1>::value && is_floating_point<T2>::value >::do_it( A, B );
|
return algorithm< is_integral<T1>::value && is_floating_point<T2>::value >::do_it(A, B);
|
||||||
}
|
}
|
||||||
</pre></div>
|
</pre></div>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue