133d722a9Sopenharmony_ci{{#title rust::Box<T> — Rust ♡ C++}}
233d722a9Sopenharmony_ci# rust::Box\<T\>
333d722a9Sopenharmony_ci
433d722a9Sopenharmony_ci### Public API:
533d722a9Sopenharmony_ci
633d722a9Sopenharmony_ci```cpp,hidelines
733d722a9Sopenharmony_ci// rust/cxx.h
833d722a9Sopenharmony_ci#
933d722a9Sopenharmony_ci# #include <type_traits>
1033d722a9Sopenharmony_ci#
1133d722a9Sopenharmony_ci# namespace rust {
1233d722a9Sopenharmony_ci
1333d722a9Sopenharmony_citemplate <typename T>
1433d722a9Sopenharmony_ciclass Box final {
1533d722a9Sopenharmony_cipublic:
1633d722a9Sopenharmony_ci  using element_type = T;
1733d722a9Sopenharmony_ci  using const_pointer =
1833d722a9Sopenharmony_ci      typename std::add_pointer<typename std::add_const<T>::type>::type;
1933d722a9Sopenharmony_ci  using pointer = typename std::add_pointer<T>::type;
2033d722a9Sopenharmony_ci
2133d722a9Sopenharmony_ci  Box(Box &&) noexcept;
2233d722a9Sopenharmony_ci  ~Box() noexcept;
2333d722a9Sopenharmony_ci
2433d722a9Sopenharmony_ci  explicit Box(const T &);
2533d722a9Sopenharmony_ci  explicit Box(T &&);
2633d722a9Sopenharmony_ci
2733d722a9Sopenharmony_ci  Box &operator=(Box &&) noexcept;
2833d722a9Sopenharmony_ci
2933d722a9Sopenharmony_ci  const T *operator->() const noexcept;
3033d722a9Sopenharmony_ci  const T &operator*() const noexcept;
3133d722a9Sopenharmony_ci  T *operator->() noexcept;
3233d722a9Sopenharmony_ci  T &operator*() noexcept;
3333d722a9Sopenharmony_ci
3433d722a9Sopenharmony_ci  template <typename... Fields>
3533d722a9Sopenharmony_ci  static Box in_place(Fields &&...);
3633d722a9Sopenharmony_ci
3733d722a9Sopenharmony_ci  void swap(Box &) noexcept;
3833d722a9Sopenharmony_ci
3933d722a9Sopenharmony_ci  // Important: requires that `raw` came from an into_raw call. Do not
4033d722a9Sopenharmony_ci  // pass a pointer from `new` or any other source.
4133d722a9Sopenharmony_ci  static Box from_raw(T *) noexcept;
4233d722a9Sopenharmony_ci
4333d722a9Sopenharmony_ci  T *into_raw() noexcept;
4433d722a9Sopenharmony_ci};
4533d722a9Sopenharmony_ci#
4633d722a9Sopenharmony_ci# } // namespace rust
4733d722a9Sopenharmony_ci```
4833d722a9Sopenharmony_ci
4933d722a9Sopenharmony_ci### Restrictions:
5033d722a9Sopenharmony_ci
5133d722a9Sopenharmony_ciBox\<T\> does not support T being an opaque C++ type. You should use
5233d722a9Sopenharmony_ci[UniquePtr\<T\>](uniqueptr.md) or [SharedPtr\<T\>](sharedptr.md) instead for
5333d722a9Sopenharmony_citransferring ownership of opaque C++ types on the language boundary.
5433d722a9Sopenharmony_ci
5533d722a9Sopenharmony_ciIf T is an opaque Rust type, the Rust type is required to be [Sized] i.e. size
5633d722a9Sopenharmony_ciknown at compile time. In the future we may introduce support for dynamically
5733d722a9Sopenharmony_cisized opaque Rust types.
5833d722a9Sopenharmony_ci
5933d722a9Sopenharmony_ci[Sized]: https://doc.rust-lang.org/std/marker/trait.Sized.html
6033d722a9Sopenharmony_ci
6133d722a9Sopenharmony_ci## Example
6233d722a9Sopenharmony_ci
6333d722a9Sopenharmony_ciThis program uses a Box to pass ownership of some opaque piece of Rust state
6433d722a9Sopenharmony_ciover to C++ and then back to a Rust callback, which is a useful pattern for
6533d722a9Sopenharmony_ciimplementing [async functions over FFI](../async.md).
6633d722a9Sopenharmony_ci
6733d722a9Sopenharmony_ci```rust,noplayground
6833d722a9Sopenharmony_ci// src/main.rs
6933d722a9Sopenharmony_ci
7033d722a9Sopenharmony_ciuse std::io::Write;
7133d722a9Sopenharmony_ci
7233d722a9Sopenharmony_ci#[cxx::bridge]
7333d722a9Sopenharmony_cimod ffi {
7433d722a9Sopenharmony_ci    extern "Rust" {
7533d722a9Sopenharmony_ci        type File;
7633d722a9Sopenharmony_ci    }
7733d722a9Sopenharmony_ci
7833d722a9Sopenharmony_ci    unsafe extern "C++" {
7933d722a9Sopenharmony_ci        include!("example/include/example.h");
8033d722a9Sopenharmony_ci
8133d722a9Sopenharmony_ci        fn f(
8233d722a9Sopenharmony_ci            callback: fn(Box<File>, fst: &str, snd: &str),
8333d722a9Sopenharmony_ci            out: Box<File>,
8433d722a9Sopenharmony_ci        );
8533d722a9Sopenharmony_ci    }
8633d722a9Sopenharmony_ci}
8733d722a9Sopenharmony_ci
8833d722a9Sopenharmony_cipub struct File(std::fs::File);
8933d722a9Sopenharmony_ci
9033d722a9Sopenharmony_cifn main() {
9133d722a9Sopenharmony_ci    let out = std::fs::File::create("example.log").unwrap();
9233d722a9Sopenharmony_ci
9333d722a9Sopenharmony_ci    ffi::f(
9433d722a9Sopenharmony_ci        |mut out, fst, snd| { let _ = write!(out.0, "{}{}\n", fst, snd); },
9533d722a9Sopenharmony_ci        Box::new(File(out)),
9633d722a9Sopenharmony_ci    );
9733d722a9Sopenharmony_ci}
9833d722a9Sopenharmony_ci```
9933d722a9Sopenharmony_ci
10033d722a9Sopenharmony_ci```cpp
10133d722a9Sopenharmony_ci// include/example.h
10233d722a9Sopenharmony_ci
10333d722a9Sopenharmony_ci#pragma once
10433d722a9Sopenharmony_ci#include "example/src/main.rs.h"
10533d722a9Sopenharmony_ci#include "rust/cxx.h"
10633d722a9Sopenharmony_ci
10733d722a9Sopenharmony_civoid f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback,
10833d722a9Sopenharmony_ci       rust::Box<File> out);
10933d722a9Sopenharmony_ci```
11033d722a9Sopenharmony_ci
11133d722a9Sopenharmony_ci```cpp
11233d722a9Sopenharmony_ci// include/example.cc
11333d722a9Sopenharmony_ci
11433d722a9Sopenharmony_ci#include "example/include/example.h"
11533d722a9Sopenharmony_ci
11633d722a9Sopenharmony_civoid f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback,
11733d722a9Sopenharmony_ci       rust::Box<File> out) {
11833d722a9Sopenharmony_ci  callback(std::move(out), "fearless", "concurrency");
11933d722a9Sopenharmony_ci}
12033d722a9Sopenharmony_ci```
121