Boost Describe Review Summary
Boost Describe was submitted by Peter Dimov. The review period lasted from
1st March 2021 until 10th March 2021, inclusive.
Overall Verdict
Boost.Describe has been accepted into Boost.
Detailed Results
In all, 13 people submitted reviews.
Of these 13, 11 reviews were an unconditional ACCEPT.
The remaining two reviews were marked CONDITIONAL ACCEPT.
This seems to be common practice, as committing firmly to accept or reject
can seem like a bold position either way. However the Boost review process
has no provision for attaching conditions to library acceptance. The
verdict must be either that the library is sufficiently well written and
documented, as well as providing sufficient utility, to be included in the
Boost offering, or it is not.
Conditional Acceptances
In this review I counted the two remaining conditional acceptances as
ACCEPT, and decided to pass the conditions as comments/suggestions on to
the author for consideration, as well as enumerate them in this report in
the hope that further study/debate is stimulated.
Libraries evolve over time, and the comments will no doubt be useful to
Peter when making future decisions about Boost.Describe.
I will deal with the conditions mentioned by Julain Blanc first.
Julian’s concerns centered around the fact that the bitfield supplied to
the describe_members macro is not additive. I will quote his example here.
Given the following code:
struct C {
int a;
std::string b;
double c;
void f(float a, int b) {
}
void g() {
}
static void s() {}
private:
int p_;
void h_(std::string const& s) {}
BOOST_DESCRIBE_CLASS(C, (), (a, b, c, f, g, s), (), (p_, h_))
};
I would expect the following:
static_assert(mp_size>::value == 6);
static_assert(mp_size>::value == 2);
That's not the case. Instead, the results are resp 3 and 1. By default,
only data members are returned, not member functions.
So, let's try another one. I want all my member functions:
static_assert(mp_size>::value == 4)
--> fails. By default, it only returns non-static functions.
So, let's try to include static function as well:
static_assert(mp_size>::value == 4)
That also fails. The result is one, now i only get the static
functions.
It looks that there's a mix of apples and orange in this enum. Some
values acts as they will include more data in the results, some on the
contrary will filter, and some will change completely the type of the
members enumerated.
This concern resonates with me, as I raised a similar (but less well
written) query with Peter in the same area.
Barrett Adair was the author of the second conditional accept. His
reasoning was along the same lines as Julian’s, quoted:
I don't like that I need to call describe_members multiple times to get
static, non-static, data, and functions. I would appreciate the addition of
mod_data and mod_nonstatic to keep the flags consistent. This is my only
acceptance condition.
Peter took time to respond to this concern:
The reason the static/nonstatic and data/function members are returned
separately is that the type of `pointer` changes. For nonstatic data, it's
M T::*. For static data, it's M*. For nonstatic function, it's R
(T::*)(A...).
For static function, it's R (*)(A...).
Since one typically does things with `pointer` in the loop over members,
it's rarely the case that you want all of these at once, because the
syntactic
form of the code manipulating them changes. So I've found it in practice
more convenient to separate them by default.
It is fair to say that in less recent variants of C++, iterating over
different pointer types would be problematic, although arguably less so
with later variants of C++ if some accessor function template overloads or
CPOs were made available in the library.
The decision on whether this should be explored rests with Peter.
Documentation and Examples
Reviewers almost universally commented on the quality and completeness of
the documentation.
Particular attention was drawn to the numerous examples that clearly
represent common real-world use cases.
Features Requested
Rainer Deyke requested the ability to annotate members with further
attributes. Peter responded that he would look into whether this was
possible while retaining compatibility with likely future standards
adoptions of reflection, which is a design goal of the library.
Maximilian Riemensberger wondered whether it would be possible to support
reference members and overloaded functions. Peter’s response was that alas,
no. The language itself is a limiting factor there.
Maximilian also requested the ability to annotate enums with associated
data. For example, representing an enum value as text when the text cannot
be reasonably computed from the value’s symbolic name. Peter agreed to
consider this further.
Maximilian also touched on the single-pass iteration issue, which brings
the number of observers who feel there is good grounds for future evolution
to four.
Overall Usefulness of the Library
The reviewers were unanimous in calling out the need for this kind of
library. From reading the reviews it is apparent that a great deal of
developer effort is duplicated in writing custom reflection mechanisms.
It struck me that (any kind of) language-level compile-time reflection
would be welcomed with open arms by the developer community. Perhaps we can
hope that the acceptance of Describe into Boost and its subsequent use can
inform and encourage the C++ language group to bring something to the
community sooner than later.
Please join me in extending gratitude to Peter, who has taken time and
painstaking effort to present us with such a useful, succinct and well
documented library.
Please also join me in thanking the reviewers, who can be sure that the
detailed analysis included has been read and in for the most part, already
elicited a response/bug-fix from Peter.
Sincerely,
Richard Hodges
--
Richard Hodges
hodges.r@gmail.com
office: +442032898513
mobile: +376380212