Supported Types
This page documents all types supported by Fory C++ serialization.
Primitive Types
All C++ primitive types are supported with efficient binary encoding:
| Type | Size | Fory TypeId | Notes |
|---|---|---|---|
bool | 1 byte | BOOL | True/false |
int8_t | 1 byte | INT8 | Signed byte |
uint8_t | 1 byte | INT8 | Unsigned byte |
int16_t | 2 byte | INT16 | Signed short |
uint16_t | 2 byte | INT16 | Unsigned short |
int32_t | 4 byte | INT32 | Signed integer |
uint32_t | 4 byte | INT32 | Unsigned integer |
int64_t | 8 byte | INT64 | Signed long |
uint64_t | 8 byte | INT64 | Unsigned long |
float | 4 byte | FLOAT32 | IEEE 754 single |
double | 8 byte | FLOAT64 | IEEE 754 double |
char | 1 byte | INT8 | Character (as signed) |
char16_t | 2 byte | INT16 | 16-bits characters |
char32_t | 4 byte | INT32 | 32-bits characters |
int32_t value = 42;
auto bytes = fory.serialize(value).value();
auto decoded = fory.deserialize<int32_t>(bytes).value();
assert(value == decoded);
String Types
| Type | Fory TypeId | Notes |
|---|---|---|
std::string | STRING | UTF-8 encoded |
std::string_view | STRING | Zero-copy view (read) |
std::u16string | STRING | UTF-16 (converted) |
binary | BINARY | Raw bytes without length |
std::string text = "Hello, World!";
auto bytes = fory.serialize(text).value();
auto decoded = fory.deserialize<std::string>(bytes).value();
assert(text == decoded);
Collection Types
Vector / List
std::vector<T> for any serializable element type:
std::vector<int32_t> numbers{1, 2, 3, 4, 5};
auto bytes = fory.serialize(numbers).value();
auto decoded = fory.deserialize<std::vector<int32_t>>(bytes).value();
// Nested vectors
std::vector<std::vector<std::string>> nested{
{"a", "b"},
{"c", "d", "e"}
};
Set
std::set<T> and std::unordered_set<T>:
std::set<std::string> tags{"cpp", "serialization", "fory"};
auto bytes = fory.serialize(tags).value();
auto decoded = fory.deserialize<std::set<std::string>>(bytes).value();
std::unordered_set<int32_t> ids{1, 2, 3};
Map
std::map<K, V> and std::unordered_map<K, V>:
std::map<std::string, int32_t> scores{
{"Alice", 100},
{"Bob", 95}
};
auto bytes = fory.serialize(scores).value();
auto decoded = fory.deserialize<std::map<std::string, int32_t>>(bytes).value();
// Unordered map
std::unordered_map<int32_t, std::string> lookup{
{1, "one"},
{2, "two"}
};
Smart Pointers
std::optional
Nullable wrapper for any type:
std::optional<int32_t> maybe_value = 42;
std::optional<int32_t> empty_value = std::nullopt;
auto bytes = fory.serialize(maybe_value).value();
auto decoded = fory.deserialize<std::optional<int32_t>>(bytes).value();
assert(decoded.has_value() && *decoded == 42);
std::shared_ptr
Shared ownership with reference tracking:
auto shared = std::make_shared<Person>("Alice", 30);
auto bytes = fory.serialize(shared).value();
auto decoded = fory.deserialize<std::shared_ptr<Person>>(bytes).value();
With reference tracking enabled (track_ref(true)):
- Shared objects are serialized once
- References to the same object are preserved
- Circular references are handled automatically
std::unique_ptr
Exclusive ownership:
auto unique = std::make_unique<Person>("Bob", 25);
auto bytes = fory.serialize(unique).value();
auto decoded = fory.deserialize<std::unique_ptr<Person>>(bytes).value();
Variant Type
std::variant<Ts...> for type-safe unions:
using MyVariant = std::variant<int32_t, std::string, double>;
MyVariant v1 = 42;
MyVariant v2 = std::string("hello");
MyVariant v3 = 3.14;
auto bytes = fory.serialize(v1).value();
auto decoded = fory.deserialize<MyVariant>(bytes).value();
assert(std::get<int32_t>(decoded) == 42);
std::monostate
Empty variant alternative:
using OptionalInt = std::variant<std::monostate, int32_t>;
OptionalInt empty = std::monostate{};
OptionalInt value = 42;
Temporal Types
Duration
std::chrono::nanoseconds:
using Duration = std::chrono::nanoseconds;
Duration d = std::chrono::seconds(30);
auto bytes = fory.serialize(d).value();
auto decoded = fory.deserialize<Duration>(bytes).value();
Timestamp
Point in time since Unix epoch:
using Timestamp = std::chrono::time_point<std::chrono::system_clock,
std::chrono::nanoseconds>;
Timestamp now = std::chrono::system_clock::now();
auto bytes = fory.serialize(now).value();
auto decoded = fory.deserialize<Timestamp>(bytes).value();
LocalDate
Days since Unix epoch:
LocalDate date{18628}; // Days since 1970-01-01
auto bytes = fory.serialize(date).value();
auto decoded = fory.deserialize<LocalDate>(bytes).value();
User-Defined Structs
Any struct can be made serializable with FORY_STRUCT:
struct Point {
double x;
double y;
double z;
};
FORY_STRUCT(Point, x, y, z);
struct Line {
Point start;
Point end;
std::string label;
};
FORY_STRUCT(Line, start, end, label);
Enum Types
Both scoped and unscoped enums are supported with FORY_ENUM:
// Scoped enum (C++11 enum class)
enum class Color { RED = 0, GREEN = 1, BLUE = 2 };
// Unscoped enum with incontinuous values
enum Priority : int32_t { LOW = -10, NORMAL = 0, HIGH = 10 };
FORY_ENUM(Priority, LOW, NORMAL, HIGH);
// Usage
Color c = Color::GREEN;
auto bytes = fory.serialize(c).value();
auto decoded = fory.deserialize<Color>(bytes).value();
Unsupported Types
Currently not supported:
- Raw pointers (
T*) - use smart pointers instead std::tuple<Ts...>- use structs insteadstd::array<T, N>- usestd::vector<T>instead- Function pointers
- References (
T&,const T&) - by value only
Related Topics
- Basic Serialization - Using these types
- Type Registration - Registering types
- Cross-Language - Cross-language compatibility