Awesome
<img src="https://raw.githubusercontent.com/veselink1/refl-cpp/master/branding/logo.svg?sanitize=true" alt="refl-cpp Logo" style="max-width: 100%;" height="140">refl-cpp is a header-only library which provides compile-time reflection and introspection capabilities to C++. By encoding type metadata in the type system, refl-cpp allows you to process types and their fields and functions via constexpr and template metaprogramming.
Using refl-cpp in your project? I want to hear about it: contact me by email (see my profile), open an issue or add the #refl-cpp tag to your topics!
Have a question? Try asking in the Gitter channel.
Want to support refl-cpp? Consider making a donation.
Table of Contents
Introduction
refl-cpp aims to provide a generic reflection system that is flexible enough to suit your needs while maintaining a relatively small API surface.
Some nice things refl-cpp supports out-of-the-box:
- custom attributes - constexpr
std::tuple
s associated with types and member descriptors - proxy types - build generic
proxy<T>
types with the same members asT
that can be used to wrap or extend functionality - overloaded functions - you only declare your overloaded function once - refl-cpp knows how to work with it
- template types - use reflection with your containers and other templates; template types are perfectly-well supported
- template functions - refl-cpp also works with template functions, when the template parameters can be inferred from the function parameters
Examples
-
Implement a simple serialization system - example-serialization.cpp - View in Compiler Explorer Implements an efficient generic serialization procedure from scratch
-
Simple SQL database abstraction - example-dao.cpp - View in Compiler Explorer Implements a basic ORM system which can generate SQL statements at compile-time from model classes using custom properties
-
Iterate base classes with
bases<>
- example-inheritance.cpp - View in Compiler Explorer Uses the built-inbases<>
attribute to iterate over a type's base classes -
Access reflection information at runtime - example-custom-rtti.cpp - View in Compiler Explorer Implements a basic runtime abstraction over refl-cpp which provides access to the reflection metadata at runtime via custom metadata objects
-
XML-based GUI with strongly-types properties - example-binding.cpp - View in Compiler Explorer Implements a system for reading XML resources with refl-cpp, by building a custom runtime reflection layer on top of refl-cpp
-
Implement a generic builder class factory - example-builders.cpp - View in Compiler Explorer Defines a generic
builder<T>
class, which implements the builder pattern for any typeT
. -
Convert fields to accessor methods - example-proxy.cpp - View in Compiler Explorer Uses the proxy feature to create a generic type
value_proxy<T>
which exposes all fields ofT
through accessors methods -
View an array of structs as a struct of arrays - example-struct-of-arrays.cpp - View in Compiler Explorer Uses the proxy feature to create a generic type
struct_of_arrays<T>
which stores all members ofT
instd::vector
, but also has anT operator[](int)
which constructs the individual objects on-demand -
Generate a struct of
std::optional
members - example-partials.cpp - View in Compiler Explorer Uses the proxy feature to create a generic typepartial<T>
which wraps all members ofT
instd::optional
Motivation
I started developing refl-cpp during my final year in high-school. I was supposed to be studying for exams, but I had just read the original Static Reflection (2017) proposal, and after realising that it wasn't coming anytime soon, I decided that I had to try to cram as many of those features at possible into a compile-time library.
The library has grown and changed a lot since the early days, but even after several years, I still haven't seen another reflection library that supports constexpr and template metaprogramming. With other libraries, you often have to walk a metadata structure at runtime, invoke function pointers, and use type-erasure. With refl-cpp, you process the type metadata at compile-time, via for_each
loops, all the types are there, and the compiler can often inline everything and generate the same code that you would have hand-written.
Performance
All utility functions in refl-cpp are constexpr (except the ones in refl::runtime
). Compilers will generally inline all loops and other constructs (when using -O2
) and generate code that runs just as fast as if it was hand-written.
Thanks to some special compile-time optimisations, type metadata is generally not instantiated (no code-gen needs to happen) when the types themselves are not used in reflection. With 0.12.2, there have also been some major reductions in compilation time when using properties #60.
That being said, a word of caution: I have observed that after around the 250 reflected members mark, compilation times start to grow rapidly. If your codebase contains lots of huge classes (+250 functions), and you need to have all of them reflected with refl-cpp
, this might be a deal breaker - benchmark before using.
Integration
Requirements
- Minimum language standard: C++17
Single-header library
To use refl-cpp as a single-header library, copy include/refl.hpp
to your include directory.
CMake
You can also consume refl-cpp as a CMake dependecy (3.14+ required, thanks @friendlyanon).
Packages
vcpkg install refl-cpp
(thanks @Vennor)conan install refl-cpp
- AUR (thanks @otreblan)
Documentation
The online documentation is built with Doxygen. Run doxygen Doxyfile
in docs/
to update it.
Testing
Run CMake with -Drefl-cpp_DEVELOPER_MODE=ON
and make the refl-cpp-tests
target.
Contributors
Run CMake with -Drefl-cpp_DEVELOPER_MODE=ON
flag. You may also want to setup a custom preset for a more convenient developer experience (see this comment on #44).
- Issue tracker - refl-cpp/issues
- Source code - refl-cpp
- Contributors - refl-cpp/contributors.md
License
- MIT License (for more details, see the license file)