cpp.md

August 3, 2026 ยท View on GitHub

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:

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:

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:

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:

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:

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:

fory.register_struct<Config>("myapp.models.Config");
fory.register_union<Holder>("myapp.models.Holder");

Usage

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 for build and usage guidance.