Overview

Rice supports the C++ standard template library (STL). To enable STL support include the rice/stl.hpp header file after the rice/rice.hpp header file.

Wrapped Versus BuiltIn Classes

Rice wraps some STL classes and copies others.

A wrapped class means that Rice creates a Ruby wrapper object for each C++ object. The Ruby wrapper enables Ruby to call methods and fields on the underlying C++ object. The C++ object is generally not copied, unless a C++ API returns it by value. Wrapped classes include:

  • std::exception

  • std::exception_ptr

  • std::map

  • std::pair

  • std::shared_ptr

  • std::type_index

  • std::type_info

  • std::unordered_map

  • std::vector

  • std::unique_ptr

In contrast, a builtin class means that Rice will copy data from a C++ object to an equivalent Ruby object. Changes in one object are not reflected in the other. Builtin classes include:

  • std::complex (to Complex)

  • std::monostate (to nil)

  • std::optional (to whatever the optional contains)

  • std::string (to String)

  • std::string_view (to String)

  • std::variant (to whatever the variant contains)

For more information see the Type Conversions section.

Automatically Generated Ruby Classes

Many STL classes are templates, and thus must be instantiated with concrete types to define actual C++ classes. A std::vector<int> is a different class than a std::vector<std::string>. This means there can be a large number of STL instantiated classes in a C++ code base.

Rice makes it easy to manually create Ruby classes for instantiated STL templates. The way to do this varies per STL type, but follows a simple naming scheme - define_pair, define_vector, etc. Please refer to the documentation for each supported STL type.

Rice can also automatically generate Ruby classes. These Ruby classes are added to the Rice::Std module. Automatic classes work well in cases where Ruby code is accessing, or modifying, wrapped objects created in C++.

Sometimes Ruby also needs to create new instances of these classes. With manually defined class names, this is easy to do. With generated class names you need to understand how Rice creates class names.

Starting in version 4.5, Rice makes use of three unicode characters to create class names that “look” like their C++ counterparts. For example, the type std::pair<std::string, double> becomes Rice::Std::Pair≺string≺char≻‚ double≻. Or assume there is a vector containing a custom class MyNamespace::MyClass. Then generated name would be Rice::Std::Vector≺MyNamespace꞉꞉MyClass≻.

The unicode characters are:

Character | Code Point

Name

:

U+A789

Modified Letter Colon

U+227A

Precedes

U+227B

Succeeds

,

U+066C

Arabic Thousands Separator

U+u00A0

Non breaking Space

To use this class in Ruby:

pair = Rice::Std::Pairstringchar≻‚ double.new

Note manual class names can be defined after auto generated class names. Rice only registers one class with Ruby, but it has two constants pointing at it. For example if you call define_pair<std::pair<std::string, double>>(StringDoublePair) after the pair has been registered, in Ruby you will have two constants pointing to the class:

Rice::Std::Pairstringchar≻‚ double
Object::StringDoublePair