This is an automated email from the ASF dual-hosted git repository.
chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git
The following commit(s) were added to refs/heads/main by this push:
new 0ffc35ab0 refactor(compiler): generate C++ unordered map for Fory map
(#3745)
0ffc35ab0 is described below
commit 0ffc35ab0eb8c44208cb9d44b5f9df718c058876
Author: Peiyang He <[email protected]>
AuthorDate: Tue Jun 9 16:04:58 2026 +0800
refactor(compiler): generate C++ unordered map for Fory map (#3745)
## Why?
C++ compiler should generate `unordered_map` for Fory `map` type, in
alignment with other languages.
## What does this PR do?
- Fory `map` type will be generated as `unordered_map` instead of `map`
- Change testcase and doc accordingly
## Related issues
N/A.
## AI Contribution Checklist
- [ ] Substantial AI assistance was used in this PR: `no`
- [ ] If `yes`, I included a completed [AI Contribution
Checklist](https://github.com/apache/fory/blob/main/AI_POLICY.md#9-contributor-checklist-for-ai-assisted-prs)
in this PR description and the required `AI Usage Disclosure`.
- [ ] If `yes`, my PR description includes the required `ai_review`
summary and screenshot evidence of the final clean AI review results
from both fresh reviewers on the current PR diff or current HEAD after
the latest code changes.
## Does this PR introduce any user-facing change?
N/A.
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
N/A.
---
compiler/fory_compiler/generators/cpp.py | 8 ++++----
compiler/fory_compiler/tests/test_generated_code.py | 12 ++++++++++++
docs/compiler/schema-idl.md | 8 ++++----
docs/guide/cpp/schema-metadata.md | 16 ++++++++--------
docs/guide/cpp/xlang-serialization.md | 14 +++++++-------
5 files changed, 35 insertions(+), 23 deletions(-)
diff --git a/compiler/fory_compiler/generators/cpp.py
b/compiler/fory_compiler/generators/cpp.py
index 54daa861c..e156cba02 100644
--- a/compiler/fory_compiler/generators/cpp.py
+++ b/compiler/fory_compiler/generators/cpp.py
@@ -241,9 +241,9 @@ class CppGenerator(BaseGenerator):
# Collect includes (including from nested types)
includes.add("<cstdint>")
- includes.add("<map>")
includes.add("<memory>")
includes.add("<string>")
+ includes.add("<unordered_map>")
includes.add("<vector>")
includes.add("<utility>")
includes.add('"fory/serialization/fory.h"')
@@ -1523,7 +1523,7 @@ class CppGenerator(BaseGenerator):
False,
parent_stack,
)
- map_type = f"std::map<{key_type}, {value_type}>"
+ map_type = f"std::unordered_map<{key_type}, {value_type}>"
if ref:
wrapper = (
"fory::serialization::SharedWeak" if weak_ref else
"std::shared_ptr"
@@ -1804,7 +1804,7 @@ class CppGenerator(BaseGenerator):
False,
parent_stack,
)
- map_type = f"std::map<{key_type}, {value_type}>"
+ map_type = f"std::unordered_map<{key_type}, {value_type}>"
if ref:
wrapper = (
"fory::serialization::SharedWeak" if weak_ref else
"std::shared_ptr"
@@ -1923,7 +1923,7 @@ class CppGenerator(BaseGenerator):
)
elif isinstance(field_type, MapType):
- includes.add("<map>")
+ includes.add("<unordered_map>")
if field_type.value_ref:
includes.add("<memory>")
if weak_ref:
diff --git a/compiler/fory_compiler/tests/test_generated_code.py
b/compiler/fory_compiler/tests/test_generated_code.py
index 1eaa3c93d..e319148d6 100644
--- a/compiler/fory_compiler/tests/test_generated_code.py
+++ b/compiler/fory_compiler/tests/test_generated_code.py
@@ -494,7 +494,19 @@ def test_generated_code_map_types_equivalent():
assert "::std::option::Option<i32>" in rust_output
cpp_output = render_files(generate_files(schemas["fdl"], CppGenerator))
+ assert "#include <unordered_map>" in cpp_output
+ assert "#include <map>" not in cpp_output
+ assert "std::unordered_map<std::string, int32_t> counts_;" in cpp_output
+ assert (
+ "std::optional<std::unordered_map<std::string, MapValue>> entries_;"
+ in cpp_output
+ )
+ assert (
+ "std::unordered_map<std::string,
fory::serialization::SharedWeak<MapValue>> "
+ "weak_entries_;" in cpp_output
+ )
assert "SharedWeak<MapValue>" in cpp_output
+ assert "std::map<" not in cpp_output
def test_rust_generated_ref_pointer_default_and_opt_out():
diff --git a/docs/compiler/schema-idl.md b/docs/compiler/schema-idl.md
index 1823ee6cd..c3d951b69 100644
--- a/docs/compiler/schema-idl.md
+++ b/docs/compiler/schema-idl.md
@@ -1478,10 +1478,10 @@ message Config {
**Language Mapping:**
-| Fory IDL | Java | Python | Go
| Rust | C++ |
JavaScript/TypeScript | Dart |
-| -------------------- | ---------------------- | ----------------- |
------------------ | ----------------------- | --------------------------------
| --------------------- | ------------------- |
-| `map<string, int32>` | `Map<String, Integer>` | `Dict[str, int]` |
`map[string]int32` | `HashMap<String, i32>` | `std::map<std::string, int32_t>`
| `Map<string, number>` | `Map<String, int>` |
-| `map<string, User>` | `Map<String, User>` | `Dict[str, User]` |
`map[string]User` | `HashMap<String, User>` | `std::map<std::string, User>`
| `Map<string, User>` | `Map<String, User>` |
+| Fory IDL | Java | Python | Go
| Rust | C++
| JavaScript/TypeScript | Dart |
+| -------------------- | ---------------------- | ----------------- |
------------------ | ----------------------- |
------------------------------------------ | --------------------- |
------------------- |
+| `map<string, int32>` | `Map<String, Integer>` | `Dict[str, int]` |
`map[string]int32` | `HashMap<String, i32>` | `std::unordered_map<std::string,
int32_t>` | `Map<string, number>` | `Map<String, int>` |
+| `map<string, User>` | `Map<String, User>` | `Dict[str, User]` |
`map[string]User` | `HashMap<String, User>` | `std::unordered_map<std::string,
User>` | `Map<string, User>` | `Map<String, User>` |
**Key Type Restrictions:**
diff --git a/docs/guide/cpp/schema-metadata.md
b/docs/guide/cpp/schema-metadata.md
index d7551fb7a..9d1c55542 100644
--- a/docs/guide/cpp/schema-metadata.md
+++ b/docs/guide/cpp/schema-metadata.md
@@ -112,14 +112,14 @@ FORY_STRUCT(Foo, (nested,
fory::F().map(T::uint32().varint(),
Supported recursive composition methods are:
-| Method | Applies to |
-| ------------------- | ------------------------------------- |
-| `list(elem)` | `std::vector<T>` and list-like fields |
-| `set(elem)` | `std::set<T>` and set-like fields |
-| `map(key, value)` | `std::map<K, V>` and map-like fields |
-| `map().key(spec)` | Override only the map key |
-| `map().value(spec)` | Override only the map value |
-| `inner(child)` | Transparent single-child carriers |
+| Method | Applies to
|
+| ------------------- |
----------------------------------------------------------------- |
+| `list(elem)` | `std::vector<T>` and list-like fields
|
+| `set(elem)` | `std::set<T>` and set-like fields
|
+| `map(key, value)` | `std::map<K, V>`, `std::unordered_map<K, V>`, and
map-like fields |
+| `map().key(spec)` | Override only the map key
|
+| `map().value(spec)` | Override only the map value
|
+| `inner(child)` | Transparent single-child carriers
|
Partial map overrides are useful when only one side needs a non-default
encoding:
diff --git a/docs/guide/cpp/xlang-serialization.md
b/docs/guide/cpp/xlang-serialization.md
index f6220235d..fc943a7d4 100644
--- a/docs/guide/cpp/xlang-serialization.md
+++ b/docs/guide/cpp/xlang-serialization.md
@@ -158,13 +158,13 @@ print(f"Timestamp: {msg.timestamp}")
### Collection Types
-| C++ Type | Java Type | Python Type | Go Type
| Rust Type |
-| ------------------------------- | -------------- | --------------- |
--------------------- | --------------- |
-| `std::vector<T>` | `List<T>` | `list` | `[]T`
| `Vec<T>` |
-| `std::vector<fory::float16_t>` | `Float16List` | `Float16Array` |
`[]float16.Float16` | `Vec<Float16>` |
-| `std::vector<fory::bfloat16_t>` | `BFloat16List` | `BFloat16Array` |
`[]bfloat16.BFloat16` | `Vec<BFloat16>` |
-| `std::set<T>` | `Set<T>` | `set` |
`map[T]struct{}` | `HashSet<T>` |
-| `std::map<K,V>` | `Map<K,V>` | `dict` |
`map[K]V` | `HashMap<K,V>` |
+| C++ Type | Java Type | Python Type
| Go Type | Rust Type |
+| ------------------------------------------- | -------------- |
--------------- | --------------------- | --------------- |
+| `std::vector<T>` | `List<T>` | `list`
| `[]T` | `Vec<T>` |
+| `std::vector<fory::float16_t>` | `Float16List` |
`Float16Array` | `[]float16.Float16` | `Vec<Float16>` |
+| `std::vector<fory::bfloat16_t>` | `BFloat16List` |
`BFloat16Array` | `[]bfloat16.BFloat16` | `Vec<BFloat16>` |
+| `std::set<T>` | `Set<T>` | `set`
| `map[T]struct{}` | `HashSet<T>` |
+| `std::map<K,V>` / `std::unordered_map<K,V>` | `Map<K,V>` | `dict`
| `map[K]V` | `HashMap<K,V>` |
### Lists and Dense Arrays
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]