mirror of
https://github.com/boostorg/pfr.git
synced 2026-01-19 04:22:13 +00:00
Write docs
This commit is contained in:
@@ -32,6 +32,7 @@ local doxygen_params =
|
||||
<doxygen:param>"ALIASES= \\
|
||||
\"forcedlink{1}=\\xmlonly<link linkend='boost.pfr.\\1'>\\endxmlonly boost::pfr::\\1\\xmlonly</link>\\endxmlonly\" \\
|
||||
\"podops=\\b See \\b Also : \\xmlonly<link linkend='boost_pfr.tutorial.three_ways_of_getting_operators'>\\endxmlonly 'Three ways of getting operators' \\xmlonly</link>\\endxmlonly\" \\
|
||||
\"fnrefl=\\b See \\b Also : \\xmlonly<link linkend='boost_pfr.tutorial.reflection_of_field_names'>\\endxmlonly 'Reflection of field names' \\xmlonly</link>\\endxmlonly\" \\
|
||||
\"customio=\\b See \\b Also : \\xmlonly<link linkend='boost_pfr.tutorial.custom_printing_of_aggregates'>\\endxmlonly 'Custom printing of aggregates' \\xmlonly</link>\\endxmlonly for info on how to implement your own manipulator with custom format.\" \\
|
||||
\"aggregate=\\xmlonly<link linkend='boost_pfr.limitations_and_configuration'>\\endxmlonly simple aggregate \\xmlonly</link>\\endxmlonly\" \\
|
||||
"
|
||||
|
||||
102
doc/pfr.qbk
102
doc/pfr.qbk
@@ -183,14 +183,14 @@ Boost.PFR adds the following out-of-the-box functionality for aggregate initiali
|
||||
* access to members by index or type
|
||||
* access to member's names by index
|
||||
* member type retrieval
|
||||
* methods for cooperation with `std::tuple`
|
||||
* methods for cooperation with `std::tuple` for members
|
||||
* methods for cooperation with `std::array` for member's names
|
||||
* methods to visit each field of the structure
|
||||
* trait to detect potential ability to reflect type, and ability to override trait's decision in user-side code
|
||||
|
||||
Boost.PFR is a header only library that does not depend on Boost. You can just copy the content of the "include" folder [@https://github.com/boostorg/pfr from the Boost.PFR github] into your project, and the library will work fine. For a version of the library without `boost::` namespace see [@https://github.com/apolukhin/pfr_non_boost PFR].
|
||||
|
||||
[caution Recommended C++ Standards are C++17 and above. Library requires at least C++14! Pre C++14 compilers (C++11, C++03...) are not supported]
|
||||
[caution Recommended C++ Standards are C++20 and above. C++17 completely enough for a user who doesn't want accessing name of structure member. Library requires at least C++14! Pre C++14 compilers (C++11, C++03...) are not supported]
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -205,6 +205,9 @@ Boost.PFR is a header only library that does not depend on Boost. You can just c
|
||||
[
|
||||
[ [pfr_quick_examples_get] ]
|
||||
[ [funcref boost::pfr::get] ]
|
||||
][
|
||||
[ [pfr_quick_examples_get_name] ]
|
||||
[ [funcref boost::pfr::get_name] ]
|
||||
][
|
||||
[ [pfr_quick_examples_ops] ]
|
||||
[
|
||||
@@ -450,12 +453,21 @@ error: static_assert failed "====================> Boost.PFR: For safety reasons
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section Reflection of field names ]
|
||||
|
||||
[pfr_example_get_name]
|
||||
|
||||
See [link boost_pfr.limitations_of_field_names_reflection [*Limitations of field names reflection]] and [link boost_pfr.limitations_and_configuration [*Limitations and Configuration]].
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section Limitations and Configuration]
|
||||
|
||||
[caution Recommended C++ Standards are C++17 and above. Library requires at least C++14! Pre C++14 compilers (C++11, C++03...) are not supported. ]
|
||||
[caution Recommended C++ Standards are C++20 and above. C++17 completely enough for a user who doesn't want accessing name of structure member. Library requires at least C++14! Pre C++14 compilers (C++11, C++03...) are not supported. ]
|
||||
|
||||
Boost.PFR library works with types that satisfy the requirements of `SimpleAggregate`: aggregate types without base classes, `const` fields, references, or C arrays:
|
||||
|
||||
@@ -477,7 +489,7 @@ struct aggregate : empty { // not a SimpleAggregate
|
||||
```
|
||||
The library may work with aggregates that don't satisfy the requirements of `SimpleAggregate`, but the behavior tends to be non-portable.
|
||||
|
||||
Boost.PFR's extraction of field name works with a `SimpleAggregate` which variables are able to be declared in any other translation unit.
|
||||
Boost.PFRs extraction of field name works with a `SimpleAggregate` which variables are able to be declared in any other translation unit.
|
||||
It's better not to use this feature with anonymous structure, local structure or a structure defined inside anonymous namespace.
|
||||
|
||||
```
|
||||
@@ -497,6 +509,8 @@ struct {
|
||||
Field's name extraction may work with a `SimpleAggregate` that does't satisfy such requirements, but the behavior tends to be non-portable.
|
||||
Try using `-fpermissive` if you have any issue with it.
|
||||
|
||||
As you see above extraction of field name feature has requirements of input type, additionally it has some requirements of compiler, see [link boost_pfr.limitations_of_field_names_reflection [*Limitations of field names reflection]] for details.
|
||||
|
||||
[h2 Configuration Macro]
|
||||
|
||||
By default Boost.PFR [*auto-detects your compiler abilities] and automatically defines the configuration macro into appropriate values. If you wish to override that behavior, just define:
|
||||
@@ -508,8 +522,8 @@ By default Boost.PFR [*auto-detects your compiler abilities] and automatically d
|
||||
[[*BOOST_PFR_HAS_GUARANTEED_COPY_ELISION*] [Define to `0` if your compiler does not implement C++17 guaranteed copy elision properly and fails to reflect aggregates with non-movable fields. Define to `1` to override Boost.PFR detection logic. ]]
|
||||
[[*BOOST_PFR_ENABLE_IMPLICIT_REFLECTION*] [Define to `0` if you are hit by lots of non-effective choices made by implicitly reflection. Define to `1` to override Boost.PFR detection logic. ]]
|
||||
[[*BOOST_PFR_ENABLE_GET_NAME_STATIC*] [On platforms where field's names extracting is not supported, the 'boost/pfr/config.hpp' header defines the BOOST_PFR_ENABLE_GET_NAME_STATIC macro equal to 0. Defining this macro as 0 before including the header disables the ability to get a field's name. ]]
|
||||
[[*BOOST_PFR_FUNCTION_SIGNATURE*] [TODO: desc it ]]
|
||||
[[*BOOST_PFR_CORE_NAME_PARSING*] [TODO: desc it ]]
|
||||
[[*BOOST_PFR_FUNCTION_SIGNATURE*] [On platforms which are unknown by Boost.PFR library, the 'boost/pfr/config.hpp' header defines the BOOST_PFR_FUNCTION_SIGNATURE macro equal to "". Defining this macro before including the header might help the library to work on your specific platform. See details [link boost_pfr.limitations_of_field_names_reflection [*here]]. ]]
|
||||
[[*BOOST_PFR_CORE_NAME_PARSING*] [On platforms which are unknown by Boost.PFR library, the 'boost/pfr/config.hpp' header defines the BOOST_PFR_CORE_NAME_PARSING macro equal to (0,0,false). Defining this macro before including the header might help the library to work on your specific platform. See details [link boost_pfr.limitations_of_field_names_reflection [*here]]. ]]
|
||||
[[*BOOST_PFR_ENABLED*] [On platforms where Boost.PFR is not supported, the `boost/pfr/config.hpp` header defines the BOOST_PFR_ENABLED macro equal to 0. Defining this macro as 0 before including the header disables the Boost.PFR library. ]]
|
||||
]
|
||||
|
||||
@@ -527,13 +541,85 @@ The Boost.PFRs reflection has some limitations that depend on a C++ Standard and
|
||||
* T must be constexpr aggregate initializable and all its fields must be constexpr default constructible
|
||||
* [funcref boost::pfr::get], [funcref boost::pfr::structure_to_tuple], [funcref boost::pfr::structure_tie], [headerref boost/pfr/core.hpp boost::pfr::tuple_element] require T to be a POD type with built-in types only.
|
||||
|
||||
The Boost.PFRs extraction of field name has some limitations that depend on a C++ Standard and compiler capabilities:
|
||||
|
||||
* T must be able to be extern.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section Limitations of field's names reflection]
|
||||
[section Limitations of field names reflection]
|
||||
|
||||
TODO: write the article and make a link on it inside "Limitations and Configuration"
|
||||
Boost.PFRs extraction of field name has been tested and successfully work on many compilers.
|
||||
|
||||
[section Define the BOOST_PFR_FUNCTION_SIGNATURE macro]
|
||||
|
||||
If you get the following error during compilation
|
||||
``
|
||||
PFRs extraction of field name could not detect your compiler.
|
||||
Please make the BOOST_PFR_FUNCTION_SIGNATURE macro use
|
||||
correct compiler macro for getting the whole function name.
|
||||
Define BOOST_PFR_CORE_NAME_PARSING to correct value after that.
|
||||
``
|
||||
then you are using a compiler that was not tested with this library.
|
||||
|
||||
[macroref BOOST_PFR_FUNCTION_SIGNATURE] must be defined to a compiler specific macro, that outputs the *whole*
|
||||
function signature including non-type template parameters.
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Fixing get_name() output]
|
||||
|
||||
Let's assume the structure `namespace A { struct A { int fn; }; }`
|
||||
|
||||
If the output of `boost::pfr::get_name<0, A::A>()`
|
||||
returns not just `fn` but also a lot of text around the `fn`
|
||||
or does not return name at all
|
||||
then you are using a compiler that was not tested with this library and you need to setup the
|
||||
[macroref BOOST_PFR_CORE_NAME_PARSING] macro.
|
||||
|
||||
Here is a short instruction:
|
||||
|
||||
# get the output of `boost::pfr::get_name<0, A::A>()`
|
||||
# define [macroref BOOST_PFR_CORE_NAME_PARSING] to
|
||||
`(skip_at_begin, skip_at_end, false, "")`, where
|
||||
* `skip_at_begin` is equal to characters count before the first occurrence of `fn` in output
|
||||
* `skip_at_end` is equal to characters count after last occurrence of `fn` in output
|
||||
# check that `boost::pfr::get_name<0, A::A>()` returns "fn"
|
||||
# if it does not return `fn`, then define BOOST_PFR_CORE_NAME_PARSING to
|
||||
`(skip_at_begin, skip_at_end, true, "T = ")`, where
|
||||
* `skip_at_begin` is equal to `skip_at_begin` at step 2
|
||||
* `skip_at_end` is equal to `skip_at_end` at step 2
|
||||
* `"T = "` is equal to characters that are right before the `fn` in output
|
||||
# (optional, but highly recommended) [@https://github.com/boostorg/pfr/issues create ticket] with
|
||||
feature request to add your compiler to supported compilers list. Include
|
||||
parameters provided to `BOOST_PFR_CORE_NAME_PARSING` macro.
|
||||
|
||||
|
||||
Consider the following example:
|
||||
|
||||
`boost::pfr::get_name<0, A::A>()` returns
|
||||
"auto __cdecl boost::pfr::detail::name_of_field_impl<struct A::A,&a->fn>(void) noexcept" while compiled with `-DBOOST_PFR_CORE_NAME_PARSING (0,0,false,"")`. Then you shall set
|
||||
`skip_at_begin` to `sizeof("auto __cdecl boost::pfr::detail::name_of_field_impl<") - 1`
|
||||
and `skip_at_end` to `sizeof(">(void) noexcept") - 1` and last parameter of macro to `"->"`.
|
||||
|
||||
``
|
||||
#define BOOST_PFR_CORE_NAME_PARSING (52, 16, true, "->")
|
||||
``
|
||||
|
||||
Another example:
|
||||
|
||||
`boost::pfr::get_name<0, A::A>()` returns
|
||||
"consteval auto boost::pfr::detail::name_of_field_impl() [with MsvcWorkaround = A::A; auto ptr = (& a.A::A::fn)]" while compiled with `-DBOOST_PFR_CORE_NAME_PARSING (0,0,false,"")`. Then you shall set
|
||||
`skip_at_begin` to `0`
|
||||
and `skip_at_end` to `sizeof(")]") - 1` and last parameter of macro to `backward("::")`.
|
||||
|
||||
``
|
||||
#define BOOST_PFR_CORE_NAME_PARSING (0, 2, true, backward("::"))
|
||||
``
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
43
example/get_name.cpp
Normal file
43
example/get_name.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
// Initial implementation by Bela Schaum, https://github.com/schaumb
|
||||
// The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669
|
||||
//
|
||||
|
||||
#include <boost/pfr/config.hpp>
|
||||
|
||||
#if BOOST_PFR_ENABLE_GET_NAME_STATIC
|
||||
//[pfr_example_get_name
|
||||
/*`
|
||||
Since C++20 it's possible to read name of structure fields by index using Boost.PFR library.
|
||||
The following example shows how to do it using [funcref boost::pfr::get_name].
|
||||
|
||||
Let's define some structure:
|
||||
*/
|
||||
#include <boost/pfr/core_name.hpp>
|
||||
|
||||
struct foo { // defining structure
|
||||
int some_integer;
|
||||
char c;
|
||||
};
|
||||
|
||||
/*`
|
||||
We can access field's names of that structure by index:
|
||||
*/
|
||||
constexpr auto r1 = boost::pfr::get_name<0, foo>(); // reading name of field with index 0, returns string `some_integer`
|
||||
constexpr auto r2 = boost::pfr::get_name<1, foo>(); // reading name of field with index 1, returns string `c`
|
||||
//] [/pfr_example_get_name]
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
#if BOOST_PFR_ENABLE_GET_NAME_STATIC
|
||||
if (r1 != "some_integer") return 1;
|
||||
if (r2 != "c") return 2;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -106,6 +106,22 @@ void test_examples() {
|
||||
//]
|
||||
}
|
||||
|
||||
#if BOOST_PFR_ENABLE_GET_NAME_STATIC
|
||||
{
|
||||
//[pfr_quick_examples_get_name
|
||||
// Get name of field by index
|
||||
|
||||
struct sample {
|
||||
int f1;
|
||||
long f2;
|
||||
};
|
||||
|
||||
std::cout << boost::pfr::get_name<0, sample>()
|
||||
<< boost::pfr::get_name<1, sample>(); // Outputs: f1 f2
|
||||
//]
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE
|
||||
{
|
||||
//[pfr_quick_examples_structure_to_tuple
|
||||
|
||||
@@ -115,25 +115,22 @@
|
||||
|| defined(__clang__)
|
||||
# define BOOST_PFR_FUNCTION_SIGNATURE __PRETTY_FUNCTION__
|
||||
# else
|
||||
// TODO: specify in the doc that this is unsupported value
|
||||
# define BOOST_PFR_FUNCTION_SIGNATURE ""
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_CORE_NAME_PARSING
|
||||
# if defined(_MSC_VER)
|
||||
// sizeof("auto __cdecl boost::pfr::detail::name_of_field_impl<") - 1, sizeof(">(void) noexcept") - 1
|
||||
// sizeof("auto __cdecl boost::pfr::detail::name_of_field_impl<") - 1, sizeof(">(void) noexcept") - 1
|
||||
# define BOOST_PFR_CORE_NAME_PARSING (52, 16, "->")
|
||||
# elif defined(__clang__)
|
||||
// sizeof("auto boost::pfr::detail::name_of_field_impl() [MsvcWorkaround = ") - 1, sizeof("}]") - 1
|
||||
// sizeof("auto boost::pfr::detail::name_of_field_impl() [MsvcWorkaround = ") - 1, sizeof("}]") - 1
|
||||
# define BOOST_PFR_CORE_NAME_PARSING (64, 2, ".")
|
||||
# elif defined(__GNUC__)
|
||||
// sizeof("consteval auto boost::pfr::detail::name_of_field_impl() [with MsvcWorkaround = ") - 1, sizeof(")]") - 1
|
||||
// sizeof("consteval auto boost::pfr::detail::name_of_field_impl() [with MsvcWorkaround = ") - 1, sizeof(")]") - 1
|
||||
# define BOOST_PFR_CORE_NAME_PARSING (79, 2, "::")
|
||||
# else
|
||||
// TODO: specify in the doc that this is unsupported value
|
||||
// TODO: .. and even if value is supported, there still no gurantee that it correct! also make a compile-fail test for such case
|
||||
// Deafult parser for other platforms... Just skip nothing!
|
||||
// Deafult parser for other platforms... Just skip nothing!
|
||||
# define BOOST_PFR_CORE_NAME_PARSING (0, 0, "")
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -24,8 +24,24 @@
|
||||
|
||||
#include <boost/pfr/tuple_size.hpp>
|
||||
|
||||
/// \file boost/pfr/core_name.hpp
|
||||
/// Contains functions \forcedlink{get_name} and \forcedlink{names_as_array} to know which names each field of any \aggregate has.
|
||||
///
|
||||
/// \fnrefl for details.
|
||||
///
|
||||
/// \b Synopsis:
|
||||
|
||||
namespace boost { namespace pfr {
|
||||
|
||||
/// \brief Returns name of a field with index `I` in \aggregate `T`.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// struct my_struct { int i, short s; };
|
||||
///
|
||||
/// assert(boost::pfr::get_name<0, my_struct>() == "i");
|
||||
/// assert(boost::pfr::get_name<1, my_struct>() == "s");
|
||||
/// \endcode
|
||||
template <std::size_t I, class T>
|
||||
constexpr auto get_name() noexcept {
|
||||
return detail::get_name<T, I>();
|
||||
@@ -37,6 +53,14 @@ constexpr auto get_name() noexcept {
|
||||
// return detail::sequence_tuple::get_by_type_impl<U>( detail::tie_as_names_tuple<T>() );
|
||||
// }
|
||||
|
||||
/// \brief Creates a `std::array` from names of fields of an \aggregate `T`.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// struct my_struct { int i, short s; };
|
||||
/// std::array<std::string_view> t = boost::pfr::structure_to_tuple<my_struct>();
|
||||
/// assert(get<0>(t) == "i");
|
||||
/// \endcode
|
||||
template <class T>
|
||||
constexpr auto names_as_array() noexcept {
|
||||
return detail::make_stdarray_from_tietuple(
|
||||
|
||||
@@ -116,6 +116,8 @@ constexpr auto clang_workaround(const T& arg) noexcept {
|
||||
|
||||
template<typename T>
|
||||
constexpr const T& clang_workaround(const T& arg) noexcept {
|
||||
// It's everything OK with this compiler
|
||||
// so we don't need a workaround here
|
||||
return arg;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user