1{{#title rust::Box<T> — Rust ♡ C++}}
2# rust::Box\<T\>
3
4### Public API:
5
6```cpp,hidelines
7// rust/cxx.h
8#
9# #include <type_traits>
10#
11# namespace rust {
12
13template <typename T>
14class Box final {
15public:
16  using element_type = T;
17  using const_pointer =
18      typename std::add_pointer<typename std::add_const<T>::type>::type;
19  using pointer = typename std::add_pointer<T>::type;
20
21  Box(Box &&) noexcept;
22  ~Box() noexcept;
23
24  explicit Box(const T &);
25  explicit Box(T &&);
26
27  Box &operator=(Box &&) noexcept;
28
29  const T *operator->() const noexcept;
30  const T &operator*() const noexcept;
31  T *operator->() noexcept;
32  T &operator*() noexcept;
33
34  template <typename... Fields>
35  static Box in_place(Fields &&...);
36
37  void swap(Box &) noexcept;
38
39  // Important: requires that `raw` came from an into_raw call. Do not
40  // pass a pointer from `new` or any other source.
41  static Box from_raw(T *) noexcept;
42
43  T *into_raw() noexcept;
44};
45#
46# } // namespace rust
47```
48
49### Restrictions:
50
51Box\<T\> does not support T being an opaque C++ type. You should use
52[UniquePtr\<T\>](uniqueptr.md) or [SharedPtr\<T\>](sharedptr.md) instead for
53transferring ownership of opaque C++ types on the language boundary.
54
55If T is an opaque Rust type, the Rust type is required to be [Sized] i.e. size
56known at compile time. In the future we may introduce support for dynamically
57sized opaque Rust types.
58
59[Sized]: https://doc.rust-lang.org/std/marker/trait.Sized.html
60
61## Example
62
63This program uses a Box to pass ownership of some opaque piece of Rust state
64over to C++ and then back to a Rust callback, which is a useful pattern for
65implementing [async functions over FFI](../async.md).
66
67```rust,noplayground
68// src/main.rs
69
70use std::io::Write;
71
72#[cxx::bridge]
73mod ffi {
74    extern "Rust" {
75        type File;
76    }
77
78    unsafe extern "C++" {
79        include!("example/include/example.h");
80
81        fn f(
82            callback: fn(Box<File>, fst: &str, snd: &str),
83            out: Box<File>,
84        );
85    }
86}
87
88pub struct File(std::fs::File);
89
90fn main() {
91    let out = std::fs::File::create("example.log").unwrap();
92
93    ffi::f(
94        |mut out, fst, snd| { let _ = write!(out.0, "{}{}\n", fst, snd); },
95        Box::new(File(out)),
96    );
97}
98```
99
100```cpp
101// include/example.h
102
103#pragma once
104#include "example/src/main.rs.h"
105#include "rust/cxx.h"
106
107void f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback,
108       rust::Box<File> out);
109```
110
111```cpp
112// include/example.cc
113
114#include "example/include/example.h"
115
116void f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback,
117       rust::Box<File> out) {
118  callback(std::move(out), "fearless", "concurrency");
119}
120```
121