WARNING: This is early documentation for an unreleased feature, only currently available in :wrapper mode. The documentation is a WIP.
Many, if not most, types in C++ are not Rust-movable. That is, you cannot initialize them using let x = y, you cannot assign them using x = y, and you cannot otherwise relocate the bits in memory, such as by std::mem::swap.
In general, it's better to make these types Rust-movable. See Rust-movable classes and Making types Rust-movable.
If the class cannot be made Rust-movable, then it will be given a less ergonomic interface, using the Ctor trait.
Ctor trait?NOTE: The API documentation and source code is at support/ctor.rs
Ctor<Output=T, Error=E> is a trait for implementing lazily evaluated values. These values are constructed in-place, in a C++-compatible way, and pinned.
However, Ctor is not a lazily-initialized value itself. It is a value initialization procedure, which returns T upon success and E upon failure. So a Ctor creates a value upon request, which is why we describe it as lazy.
Since exceptions are disabled at Google, we currently only work with Error=Infallible, and for exposition will omit the error type.
Functions accepting and returning a non-Rust movable value in C++ will accept and return an impl Ctor in Rust, as so:
pub fn accepts_value(x: impl Ctor<Output=CppType, ...>) {...} pub fn returns() -> impl Ctor<Output=CppType, ...> {...}
The easiest way to work with these types in Rust is to box them into a Pin<Box<T>> using Box::emplace(). Then they can be passed by value using mov!(x) (similar to std::move in C++), and by mutable reference using .as_mut(). For example:
use ctor::{Emplace, mov}; // gives Box::emplace and mov!(). let mut x /* : Pin<Box<T>> */ = Box::emplace(returns()); takes_mutable_reference(x.as_mut()); takes_const_reference(&x); accepts_value(mov!(x));
NOTE: The call to returns() does not construct a value of type CppType, it merely returns a Ctor<Output=CppType>, which is a procedure to lazily create such a value. A CppType is created only when the Ctor is executed as part of the Box::emplace(...) expression in the caller.
If you happen to be directly passing a return value into a parameter, you can avoid the intermediate boxed value:
accepts(returns());
If you want to avoid heap allocations in general, you will need to use the more advanced features of ctor.rs.