Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
070d51e
Isolated resources that use C++20 hacks
liuzicheng1987 Aug 10, 2026
94f0913
Implemented bind_to_tuple and num_fields
liuzicheng1987 Aug 11, 2026
bd1ca57
Adapted surrounding headers
liuzicheng1987 Aug 11, 2026
ec50d13
Added concat_literals
liuzicheng1987 Aug 12, 2026
3ac42d5
Fixed two bugs
liuzicheng1987 Aug 15, 2026
43981f6
Made everything consteval
liuzicheng1987 Aug 15, 2026
02037cf
Make sure rename is applied
liuzicheng1987 Aug 15, 2026
36fba5c
Started working on inheritance
liuzicheng1987 Aug 15, 2026
8bffdff
Made inheritance work
liuzicheng1987 Aug 16, 2026
9c619dd
Minor code beautification
liuzicheng1987 Aug 16, 2026
5e6489a
Fixed typo in test
liuzicheng1987 Aug 16, 2026
02d8535
Began developing enums
liuzicheng1987 Aug 16, 2026
dd996f5
Added support for enums
liuzicheng1987 Aug 16, 2026
cd09619
Updated range_defined
liuzicheng1987 Aug 16, 2026
e64f181
Started adapting the README
liuzicheng1987 Aug 18, 2026
c3da851
Renamed the flag
liuzicheng1987 Aug 18, 2026
5b5b17f
Write workaround to avoid false positive warning
liuzicheng1987 Aug 18, 2026
18f0a95
Fixed minor issues in the tests
liuzicheng1987 Aug 18, 2026
40d64f2
Added documentation
liuzicheng1987 Aug 18, 2026
aaca276
Fixed issues in the C++-20 build
liuzicheng1987 Aug 20, 2026
ed74536
Fixed first test failure: Make sure that enum ranges work
liuzicheng1987 Aug 22, 2026
5d30c0b
Fixed error in test
liuzicheng1987 Aug 22, 2026
2096a3b
Don't automatically set CPP26 to true
liuzicheng1987 Aug 22, 2026
bedcbe3
Removed remaining references to enchantum
liuzicheng1987 Aug 22, 2026
4fdb50f
Added C++ 26 reflection to the pipeline
liuzicheng1987 Aug 22, 2026
ff05444
Get type name using C++ 26
liuzicheng1987 Aug 22, 2026
686e64e
Explicitly exclude headers; better handling for member pointers
liuzicheng1987 Aug 22, 2026
17ce933
Added missing include
liuzicheng1987 Aug 23, 2026
fe59631
Workaround to get CBOR and UBJSON up-and-running
liuzicheng1987 Aug 23, 2026
0cb7a6e
Fix get_member_ptr_name for MSVC
liuzicheng1987 Aug 23, 2026
02d8566
Removed enchantum::Enum
liuzicheng1987 Aug 23, 2026
7b6ab5f
Simplified get_member_ptr_name
liuzicheng1987 Aug 23, 2026
e67ee10
Workaround for issue in Clang
liuzicheng1987 Aug 23, 2026
2f3cacd
Catch clang pragma
liuzicheng1987 Aug 23, 2026
072baa2
Do not use libc++
liuzicheng1987 Aug 23, 2026
9b44671
Temporarily removed GCC 16
liuzicheng1987 Aug 23, 2026
8977128
Added pragmas araound parquet
liuzicheng1987 Aug 23, 2026
5cd5be1
Use the cpp20 solution for member pointers
liuzicheng1987 Aug 23, 2026
6bdd1a7
Rearrange Result
liuzicheng1987 Aug 23, 2026
d6a16b6
Fix benchmarks
liuzicheng1987 Aug 23, 2026
804219d
Exclude CBOR and UBJSON in LLVM
liuzicheng1987 Aug 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 43 additions & 22 deletions .github/workflows/linux.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: linux

on: [ push, pull_request ]

env:
env:
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"

jobs:
Expand All @@ -15,32 +15,45 @@ jobs:
compiler-version: [11, 12, 13, 14, 16, 17, 18]
cxx: [20, 23]
exclude:
- compiler: gcc
- compiler: gcc
compiler-version: 16
- compiler: gcc
- compiler: gcc
compiler-version: 17
- compiler: gcc
- compiler: gcc
compiler-version: 18
- compiler: llvm
compiler-version: 11
- compiler: llvm
- compiler: llvm
compiler-version: 12
- compiler: llvm
- compiler: llvm
compiler-version: 13
- compiler: llvm
- compiler: llvm
compiler-version: 14
- compiler: gcc
compiler-version: 11
cxx: 23
cxx: 23
- compiler: gcc
compiler-version: 12
cxx: 23
- compiler: llvm
cxx: 23
- compiler: llvm
compiler-version: 16
cxx: 23
cxx: 23
- compiler: llvm
compiler-version: 17
cxx: 23
cxx: 23
- compiler: llvm
cxx: 23
format: "CBOR"
- compiler: llvm
cxx: 23
format: "UBJSON"
- compiler: llvm
cxx: 23
format: "benchmarks"
- compiler: llvm
cxx: 23
format: "headers"
# TODO: Include reflection runners, once gcc-16 is in the repo.
name: "${{ github.job }} (${{ matrix.format }}-C++${{ matrix.cxx }}-${{ matrix.compiler }}-${{ matrix.compiler-version }})"
concurrency:
group: "linux-${{ github.ref }}-${{ github.job }}-${{ matrix.format }}-C++${{ matrix.cxx }}-${{ matrix.compiler }}-${{ matrix.compiler-version }}"
Expand All @@ -64,7 +77,11 @@ jobs:
run: |
sudo apt update
if [[ "${{ matrix.compiler-version }}" == 11 ]]; then
sudo apt install -y ninja-build g++-11
sudo apt install -y ninja-build g++-11
elif [[ "${{ matrix.compiler }}" == "gcc" && "${{ matrix.compiler-version }}" == 16 ]]; then
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt update
sudo apt install -y ninja-build g++-16
else
sudo apt install -y ninja-build
fi
Expand All @@ -78,25 +95,29 @@ jobs:
export CXX=g++-${{ matrix.compiler-version }}
fi
$CXX --version
EXTRA_CMAKE_FLAGS=""
if [[ "${{ matrix.reflection }}" == "on" ]]; then
EXTRA_CMAKE_FLAGS="-DREFLECTCPP_USE_CPP26_REFLECTION=ON -DCMAKE_CXX_FLAGS=-freflection"
fi
if [[ "${{ matrix.format }}" == "JSON" ]]; then
cmake -S . -B build -G Ninja -DCMAKE_CXX_STANDARD=${{ matrix.cxx }} -DCMAKE_CXX_STANDARD=20 -DREFLECTCPP_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release
cmake -S . -B build -G Ninja -DCMAKE_CXX_STANDARD=${{ matrix.cxx }} -DREFLECTCPP_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release $EXTRA_CMAKE_FLAGS
elif [[ "${{ matrix.format }}" == "benchmarks" ]]; then
cmake -S . -B build -G Ninja -DCMAKE_CXX_STANDARD=${{ matrix.cxx }} -DCMAKE_CXX_STANDARD=20 -DREFLECTCPP_BUILD_BENCHMARKS=ON -DREFLECTCPP_ALL_FORMATS=ON -DCMAKE_BUILD_TYPE=Release
cmake -S . -B build -G Ninja -DCMAKE_CXX_STANDARD=${{ matrix.cxx }} -DREFLECTCPP_BUILD_BENCHMARKS=ON -DREFLECTCPP_ALL_FORMATS=ON -DCMAKE_BUILD_TYPE=Release $EXTRA_CMAKE_FLAGS
elif [[ "${{ matrix.format }}" == "headers" ]]; then
cmake -S . -B build -G Ninja -DCMAKE_CXX_STANDARD=${{ matrix.cxx }} -DCMAKE_CXX_STANDARD=20 -DREFLECTCPP_CHECK_HEADERS=ON -DCMAKE_BUILD_TYPE=Release
cmake -S . -B build -G Ninja -DCMAKE_CXX_STANDARD=${{ matrix.cxx }} -DREFLECTCPP_CHECK_HEADERS=ON -DCMAKE_BUILD_TYPE=Release $EXTRA_CMAKE_FLAGS
else
cmake -S . -B build -G Ninja -DCMAKE_CXX_STANDARD=${{ matrix.cxx }} -DCMAKE_CXX_STANDARD=20 -DREFLECTCPP_BUILD_TESTS=ON -DREFLECTCPP_JSON=OFF -DREFLECTCPP_${{ matrix.format }}=ON -DCMAKE_BUILD_TYPE=Release
cmake -S . -B build -G Ninja -DCMAKE_CXX_STANDARD=${{ matrix.cxx }} -DREFLECTCPP_BUILD_TESTS=ON -DREFLECTCPP_JSON=OFF -DREFLECTCPP_${{ matrix.format }}=ON -DCMAKE_BUILD_TYPE=Release $EXTRA_CMAKE_FLAGS
fi
cmake --build build -j4
- name: Run tests
if: (matrix.format != 'benchmarks') && (matrix.format != 'headers')
run: |
ctest --test-dir build --output-on-failure
- name: Run benchmarks
if: matrix.format == 'benchmarks'
- name: Run benchmarks
if: matrix.format == 'benchmarks'
run: |
echo '# Benchmarks' >> $GITHUB_STEP_SUMMARY
echo '## Benchmarks across different formats' >> $GITHUB_STEP_SUMMARY
echo '# Benchmarks' >> $GITHUB_STEP_SUMMARY
echo '## Benchmarks across different formats' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=canada_read >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=canada_write >> $GITHUB_STEP_SUMMARY
Expand All @@ -105,7 +126,7 @@ jobs:
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=person_read >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=person_write >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo '## Benchmarks for JSON' >> $GITHUB_STEP_SUMMARY
echo '## Benchmarks for JSON' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
./build/benchmarks/json/reflect-cpp-json-benchmarks --benchmark_filter=person_read >> $GITHUB_STEP_SUMMARY
./build/benchmarks/json/reflect-cpp-json-benchmarks --benchmark_filter=canada >> $GITHUB_STEP_SUMMARY
Expand Down
11 changes: 10 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,14 @@ option(REFLECTCPP_CHECK_HEADERS "Make sure that all headers are self-contained"

option(REFLECTCPP_USE_BUNDLED_DEPENDENCIES "Use the bundled dependencies" ON)

option(REFLECTCPP_USE_CPP26_REFLECTION "Use standard C++ reflection (requires C++-26)" OFF)
option(REFLECTCPP_USE_STD_EXPECTED "Use std::expected instead of the built-in Result type (requires C++-23)" OFF)

if(REFLECTCPP_USE_STD_EXPECTED)
if(REFLECTCPP_USE_CPP26_REFLECTION)
if(NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 26)
endif()
elseif(REFLECTCPP_USE_STD_EXPECTED)
if(NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 23)
endif()
Expand Down Expand Up @@ -229,6 +234,10 @@ if(REFLECTCPP_BUILD_SHARED)
target_compile_definitions(reflectcpp PUBLIC RFL_BUILD_SHARED)
endif()

if(REFLECTCPP_USE_CPP26_REFLECTION)
target_compile_definitions(reflectcpp PUBLIC REFLECTCPP_USE_CPP26_REFLECTION)
endif()

if(REFLECTCPP_USE_STD_EXPECTED)
target_compile_definitions(reflectcpp PUBLIC REFLECTCPP_USE_STD_EXPECTED)
endif()
Expand Down
45 changes: 33 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

![image](banner1.png)

**reflect-cpp** is a C++-20 library for **fast serialization, deserialization and validation** using reflection, similar to [pydantic](https://github.com/pydantic/pydantic) in Python, [serde](https://github.com/serde-rs) in Rust, [encoding](https://github.com/golang/go/tree/master/src/encoding) in Go or [aeson](https://github.com/haskell/aeson/tree/master) in Haskell.
**reflect-cpp** is a C++-20/C++-26 library for **fast serialization, deserialization and validation** using reflection, similar to [pydantic](https://github.com/pydantic/pydantic) in Python, [serde](https://github.com/serde-rs) in Rust, [encoding](https://github.com/golang/go/tree/master/src/encoding) in Go or [aeson](https://github.com/haskell/aeson/tree/master) in Haskell.

reflect-cpp supports C++-26 reflection, but most of the functionality is also available in C++-20, except where explicitly noted otherwise.

Moreover, reflect-cpp is the basis for [sqlgen](https://github.com/getml/sqlgen), a **modern, type-safe ORM and SQL query generator** for C++20, inspired by Python's SQLAlchemy/SQLModel and Rust's Diesel. It provides a fluent, composable interface for database operations with compile-time type checking and SQL injection protection.

Expand Down Expand Up @@ -51,6 +53,7 @@ reflect-cpp and sqlgen fill important gaps in C++ development. They reduce boile

### More in our [documentation](https://rfl.getml.com):
- [Installation ↗](https://rfl.getml.com/install/#option-2-compilation-using-cmake)
- [C++26 reflection ↗](https://rfl.getml.com/cpp26_reflection)
- [Benchmarks ↗](https://rfl.getml.com/benchmarks)
- [How to contribute ↗](https://rfl.getml.com/contributing)
- [Compiling and running the tests ↗](https://rfl.getml.com/contributing/#compiling-and-running-the-tests)
Expand All @@ -62,17 +65,17 @@ reflect-cpp provides a unified reflection-based interface across different seria

The following table lists the serialization formats currently supported by reflect-cpp and the underlying libraries used:

| Format | Library | Version | License | Remarks |
|--------------|------------------------------------------------------|--------------|------------| -----------------------------------------------------|
| JSON | [yyjson](https://github.com/ibireme/yyjson) | >= 0.8.0 | MIT | out-of-the-box support, included in this repository |
| Avro | [avro-c](https://avro.apache.org/docs/1.11.1/api/c/) | >= 1.11.3 | Apache 2.0 | Schemaful binary format |
| Format | Library | Version | License | Remarks |
|---------------------|------------------------------------------------------|--------------|------------| -----------------------------------------------------|
| JSON | [yyjson](https://github.com/ibireme/yyjson) | >= 0.8.0 | MIT | out-of-the-box support, included in this repository |
| Avro | [avro-c](https://avro.apache.org/docs/1.11.1/api/c/) | >= 1.11.3 | Apache 2.0 | Schemaful binary format |
| Boost.Serialization | [Boost.Serialization](https://www.boost.org/doc/libs/release/libs/serialization/) | >= 1.74.0 | BSL 1.0 | Streaming binary format with archive interop |
| BSON | [libbson](https://github.com/mongodb/mongo-c-driver) | >= 1.25.1 | Apache 2.0 | JSON-like binary format |
| Cap'n Proto | [capnproto](https://capnproto.org) | >= 1.0.2 | MIT | Schemaful binary format |
| CBOR | [jsoncons](https://github.com/danielaparker/jsoncons)| >= 0.176.0 | BSL 1.0 | JSON-like binary format |
| cli | *(none)* | *(none)* | MIT | Command line interface |
| env | *(none)* | *(none)* | MIT | Environment variables |
| Cereal | [Cereal](https://uscilab.github.io/cereal/) | >= 1.3.2 | BSD | C++ serialization library with multiple formats |
| BSON | [libbson](https://github.com/mongodb/mongo-c-driver) | >= 1.25.1 | Apache 2.0 | JSON-like binary format |
| Cap'n Proto | [capnproto](https://capnproto.org) | >= 1.0.2 | MIT | Schemaful binary format |
| CBOR | [jsoncons](https://github.com/danielaparker/jsoncons)| >= 0.176.0 | BSL 1.0 | JSON-like binary format |
| cli | *(none)* | *(none)* | MIT | Command line interface |
| env | *(none)* | *(none)* | MIT | Environment variables |
| Cereal | [Cereal](https://uscilab.github.io/cereal/) | >= 1.3.2 | BSD | C++ serialization library with multiple formats |
| CSV | [Apache Arrow](https://arrow.apache.org/) | >= 21.0.0 | Apache 2.0 | Tabular textual format |
| flexbuffers | [flatbuffers](https://github.com/google/flatbuffers) | >= 23.5.26 | Apache 2.0 | Schema-less version of flatbuffers, binary format |
| msgpack | [msgpack-c](https://github.com/msgpack/msgpack-c) | >= 6.0.0 | BSL 1.0 | JSON-like binary format |
Expand Down Expand Up @@ -666,11 +669,29 @@ Finally, it is very easy to extend full support to your own classes, refer to th

## Installation

The following compilers are supported:
The following compilers are supported for C++-20:
- GCC 11.4 or higher
- Clang 14.0 or higher
- MSVC 17.8 (19.38) or higher

The following compilers are supported for C++-26:
- GCC 16.2 or higher

### Compiling with C++-26 reflection

To compile reflect-cpp using the standard C++ reflection facilities, pass the CMake option
`REFLECTCPP_USE_CPP26_REFLECTION` together with the compiler flag that activates reflection
support in your compiler (`-freflection` for GCC, `-freflection-latest` for Clang):

```bash
cmake -S . -B build -DCMAKE_CXX_STANDARD=26 -DCMAKE_BUILD_TYPE=Release -DREFLECTCPP_USE_CPP26_REFLECTION=ON -DCMAKE_CXX_FLAGS="-freflection"
cmake --build build -j 4
```

With C++-26 reflection, fixed-size C arrays and inheritance are supported out of the box (no
`-DREFLECT_CPP_C_ARRAYS_OR_INHERITANCE` flag needed), and there are no range restrictions for
enums. Refer to the [documentation](https://rfl.getml.com/cpp26_reflection) for details.

### Using vcpkg

https://vcpkg.io/en/package/reflectcpp
Expand Down
4 changes: 2 additions & 2 deletions benchmarks/json/person.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ rfl::Result<std::vector<Person>> yyjson_to_children(yyjson_val *_val) {
while ((val = yyjson_arr_iter_next(&iter))) {
auto r = yyjson_to_person(val);
if (!r) {
return error(r.error());
return rfl::error(r.error());
}
children.emplace_back(std::move(*r));
}
Expand Down Expand Up @@ -220,7 +220,7 @@ rfl::Result<Person> yyjson_to_person(yyjson_val *_val) {
for (const auto &err : errors) {
std::cout << err.what() << std::endl;
}
return error(errors[0]);
return rfl::error(errors[0]);
}
return person;
}
Expand Down
11 changes: 11 additions & 0 deletions docs/c_arrays_and_inheritance.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ inheritance altogether.
Note that C arrays are not the same thing as `std::array`. `std::array` is always
supported and is the recommended alternative.

!!! note "C++-26 reflection"

If you compile reflect-cpp with C++-26 reflection (see [C++26 reflection](cpp26_reflection.md)),
then none of the restrictions in this section apply: fixed-size C arrays and inheritance are
supported out of the box, no flag is required, and the fields may be spread out over
multiple structs.

If you want support for these, you will have to pass the flag `-D REFLECT_CPP_C_ARRAYS_OR_INHERITANCE`
during compilation.

Expand Down Expand Up @@ -85,6 +92,10 @@ struct Derived : Base {
};
```

Note that this restriction does not apply when compiling with C++-26 reflection: with C++-26,
the fields of the base class and the fields of the derived class are combined automatically,
so the example above works as well.

The recommended alternative is to simply use `rfl::Flatten`, which
has no such limitation:

Expand Down
Loading
Loading