A C++ enum
is mapped to a Rust struct
with a similar API to a Rust enum
.
- The enumerated constants are present as associated constants:
MyEnum::kFoo
in C++ isMyEnum::kFoo
in Rust. - The enum can be converted to and from its underlying type using
From
andInto
. For example,static_cast<int32_t>(x)
isi32::from(x)
in Rust, and vice versastatic_cast<MyEnum>(x)
isMyEnum::from(x)
.
However, a C++ enum is not a Rust enum. Some features of Rust enums are not supported:
- C++ enums must be converted using
From
andInto
, notas
. - C++ enums do not have exhaustive pattern matching.
Given the following C++ header:
cs/file:examples/cpp/enum/example.h class:Color
Crubit will generate the following bindings:
cs/file:examples/cpp/enum/example_generated.rs content:^([^/\n])([^!\n]|$)[^\n]*
A C++ enum
cannot be translated directly to a Rust enum
, because C++ enums
are "representationally non-exhaustive": a C++ enum
can have any value
supported by the underlying type, even one not listed in the enumerators. For
example, in the enum above, static_cast<Color>(42)
is a valid instance of
Color
, even though none of kRed
, kBlue
, or kGreen
have that value.
Rust enums, in contrast, are representationally exhaustive. An enum declares a
closed set of valid discriminants, and it is undefined behavior to
attempt to create an enum with a value outside of that set, whether it's via
transmute
, a raw pointer cast, or Crubit. The behavior is undefined the moment
the invalid value is created, even if it is never used.
Since a value like static_cast<Color>(42)
is not in the list of enumerators, a
Rust enum
cannot be used to represent an arbitrary C++ enum
. Instead, the
Rust bindings are a struct
. This struct
is given the most natural and
enum
-like API possible, though there are still gaps. (Casts using as
, for
example, will not work with a C++ enum.)
The #[non_exhaustive]
attribute on an enum communicates to external
crates that more variants may be added in the future, and so a match
requires
a wildcard branch. Within the defining crate, non_exhaustive
has no effect. It
remains undefined behavior to transmute
from integers not declared by the
enum.