| --- |
| title: C++ |
| sidebar_position: 5 |
| id: cpp |
| license: | |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --- |
| |
| ## Output Layout |
| |
| C++ output is one header per schema file, for example: |
| |
| - `<cpp_out>/addressbook.h` |
| |
| ## Type Generation |
| |
| Messages generate `final` classes with typed accessors and byte helpers: |
| |
| ```cpp |
| class Person final { |
| public: |
| class PhoneNumber final { |
| public: |
| const std::string& number() const; |
| std::string* mutable_number(); |
| template <class Arg, class... Args> |
| void set_number(Arg&& arg, Args&&... args); |
| |
| fory::Result<std::vector<uint8_t>, fory::Error> to_bytes() const; |
| static fory::Result<PhoneNumber, fory::Error> from_bytes( |
| const uint8_t* data, std::size_t size); |
| static fory::Result<PhoneNumber, fory::Error> from_bytes(const std::vector<uint8_t>& data); |
| }; |
| |
| const std::string& name() const; |
| std::string* mutable_name(); |
| template <class Arg, class... Args> |
| void set_name(Arg&& arg, Args&&... args); |
| |
| const Animal& pet() const; |
| Animal* mutable_pet(); |
| }; |
| ``` |
| |
| Optional message fields generate `has_xxx`, `mutable_xxx`, and `clear_xxx` APIs: |
| |
| ```cpp |
| class Envelope final { |
| public: |
| bool has_payload() const { return payload_ != nullptr; } |
| const Envelope::Payload& payload() const { return *payload_; } |
| Envelope::Payload* mutable_payload() { |
| if (!payload_) { |
| payload_ = std::make_unique<Envelope::Payload>(); |
| } |
| return payload_.get(); |
| } |
| void clear_payload() { payload_.reset(); } |
| |
| private: |
| std::unique_ptr<Envelope::Payload> payload_; |
| }; |
| ``` |
| |
| Unions generate `std::variant` wrappers: |
| |
| ```cpp |
| class Animal final { |
| public: |
| enum class AnimalCase : uint32_t { |
| DOG = 1, |
| CAT = 2, |
| }; |
| |
| static Animal dog(Dog v); |
| static Animal cat(Cat v); |
| |
| AnimalCase animal_case() const noexcept; |
| uint32_t animal_case_id() const noexcept; |
| |
| bool is_dog() const noexcept; |
| const Dog* as_dog() const noexcept; |
| Dog* as_dog() noexcept; |
| const Dog& dog() const; |
| Dog& dog(); |
| |
| template <class Visitor> |
| decltype(auto) visit(Visitor&& vis) const; |
| |
| private: |
| std::variant<Dog, Cat> value_; |
| }; |
| ``` |
| |
| Generated headers include `FORY_UNION`, `FORY_ENUM`, and `FORY_STRUCT` macros |
| for serialization metadata. Field and payload configuration is embedded in the |
| generated `FORY_STRUCT`/`FORY_UNION` entries. |
| |
| ## Registration |
| |
| Generated registration function: |
| |
| ```cpp |
| inline void register_types(fory::serialization::BaseFory& fory) { |
| fory.register_union<Animal>(106); |
| fory.register_enum<Person::PhoneType>(101); |
| fory.register_struct<Person::PhoneNumber>(102); |
| fory.register_struct<Person>(100); |
| fory.register_struct<Dog>(104); |
| fory.register_struct<Cat>(105); |
| fory.register_struct<AddressBook>(103); |
| } |
| ``` |
| |
| For schemas without explicit `[id=...]`, generated registration uses computed numeric IDs: |
| |
| ```cpp |
| fory.register_enum<Status>(1124725126); |
| fory.register_union<Wrapper>(1471345060); |
| fory.register_struct<Envelope>(3022445236); |
| fory.register_union<Envelope::Detail>(1609214087); |
| fory.register_struct<Envelope::Payload>(2862577837); |
| ``` |
| |
| If `option enable_auto_type_id = false;` is set: |
| |
| ```cpp |
| fory.register_struct<Config>("myapp.models.Config"); |
| fory.register_union<Holder>("myapp.models.Holder"); |
| ``` |
| |
| ## Usage |
| |
| ```cpp |
| addressbook::Person person; |
| person.set_name("Alice"); |
| *person.mutable_pet() = addressbook::Animal::dog(addressbook::Dog{}); |
| |
| auto bytes = person.to_bytes(); |
| auto restored = addressbook::Person::from_bytes(bytes.value()); |
| ``` |
| |
| ## gRPC Service Companions |
| |
| With `--grpc`, C++ emits `<stem>.service.h`, `<stem>.service.grpc.h`, and `<stem>.service.grpc.cc`. The API header contains synchronous interfaces and route constants under `::<namespace>::service`; the binding header contains generated `grpc::SerializationTraits` plus client and server wrappers under `::<namespace>::service::grpc`. See [C++ gRPC](../../grpc/cpp.md) for build and usage guidance. |