Copyright © 2016-2025 Antony Polukhin
根据 Boost 软件许可证版本 1.0 发布。(参见随附文件 LICENSE_1_0.txt 或在 https://boost.ac.cn/LICENSE_1_0.txt 复制)
目录
Boost.PFR 是一个 C++14 库,用于非常基本的反射。它允许您通过索引访问结构元素,并为用户定义的类型提供其他类似 std::tuple
的方法,而无需宏或样板代码。
#include <iostream> #include <string> #include "boost/pfr.hpp" struct some_person { std::string name; unsigned birth_year; }; int main() { some_person val{"Edgar Allan Poe", 1809}; std::cout << boost::pfr::get<0>(val) // No macro! << " was born in " << boost::pfr::get<1>(val); // Works with any aggregate initializables! std::cout << boost::pfr::io(val); // Outputs: {"Edgar Allan Poe", 1809} }
假设您正在为数据库编写包装库。根据 Boost.PFR 的用法,用户代码看起来会不同。
没有 Boost.PFR |
使用 Boost.PFR |
---|---|
#include <db/api.hpp> struct user_info { std::int64_t id; std::string name, email, login; }; user_info retrieve_friend(std::string_view name) { std::tuple info_tuple = db::one_row_as<std::int64_t, std::string, std::string, std::string>( "SELECT id, name, email, login FROM user_infos WHERE name=$0", name ); ///////////////////////////////////////////////////////////////////////////// user_info info { std::move(std::get<0>(info_tuple)), std::move(std::get<1>(info_tuple)), std::move(std::get<2>(info_tuple)), std::move(std::get<3>(info_tuple)), } ///////////////////////////////////////////////////////////////////////////// auto friend_info = ask_user_for_friend(std::move(info)); db::insert( "INSERT INTO user_infos(id, name, email, login) VALUES ($0, $1, $2, $3)", friend_info.id, ////////////////////////////////////////////////////// friend_info.name, // Users are forced to enumerate fields because your friend_info.email, // library can not iterate over the fields of a user friend_info.login // provided structure ); return friend_info; } |
#include <db/api.hpp> struct user_info { std::int64_t id; std::string name, email, login; }; user_info retrieve_friend(std::string_view name) { // With Boost.PFR you can put data directly into user provided structures user_info info = db::one_row_as<user_info>( "SELECT id, name, email, login FROM user_infos WHERE name=$0", name ); ////////////////// No boilerplate code to move data around ////////////////// ///////////////////////////////////////////////////////////////////////////// auto friend_info = ask_user_for_friend(std::move(info)); db::insert( "INSERT INTO user_infos(id, name, email, login) VALUES ($0, $1, $2, $3)", friend_info ///////////////////////////////////////////////////////// // Boost.PFR allows you to iterate over all the fields // of a user provided structure // ); return friend_info; } |
否则,您的库可能需要为用户类型提供一个自定义点。
没有 Boost.PFR |
使用 Boost.PFR |
---|---|
#include <db/api.hpp> struct user_info { std::int64_t id; std::string name, email, login; }; /// Customizations via hand-written code //////////////////////////////////////// auto db_api_tie(user_info& ui) noexcept { return std::tie(ui.id, ui.name, ui.email, ui.login); } auto db_api_tie(const user_info& ui) noexcept { return std::tie(ui.id, ui.name, ui.email, ui.login); } ///////////////////////////////////////////////////////////////////////////////// |
#include <db/api.hpp> struct user_info { std::int64_t id; std::string name, email, login; }; //////// With Boost.PFR there's no need in hand written customizations ////////// ///////////////////////////////////////////////////////////////////////////////// |
假设您正在编写一个序列化库。使用 Boost.PFR 序列化用户提供的结构(和嵌套结构)就像以下一样简单:
void Write(Writer& writer, int value); void Write(Writer& writer, std::string_view value); template <typename T> std::enable_if_t<boost::pfr::is_implicitly_reflectable_v<T>> Write(Writer& writer, const T& value) { boost::pfr::for_each_field( value, [&writer](const auto& field) { Write(writer, field); }); }
使用 Boost.PFR,代码更短、更易读、更令人愉悦。
![]() |
注意 |
---|---|
以上所有示例都受到 🐙 userver 框架 中 Boost.PFR 用法的启发。 |
Boost.PFR 为可聚合初始化的结构提供了以下开箱即用的功能:
std::tuple
协作的方法std::array
协作的方法Boost.PFR 是一个仅标头库,不依赖于 Boost。您可以直接将 Boost.PFR github 的 "include" 文件夹内容 复制到您的项目中,该库即可正常工作。要获取不带 boost::
命名空间的版本,请参阅 PFR。
![]() |
注意 |
---|---|
推荐使用的 C++ 标准是 C++20 及更高版本。对于不想访问结构成员名称的用户来说,C++17 完全足够。该库至少需要 C++14!不支持 C++14 之前的编译器(C++11、C++03...)。 |