////
Copyright 2020, 2021 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////

[#reference]
# Reference
:idprefix: ref_

## <boost/describe/enum.hpp>

```
#define BOOST_DESCRIBE_ENUM(E, ...) /*...*/

#define BOOST_DESCRIBE_NESTED_ENUM(E, ...) /*...*/

#define BOOST_DEFINE_ENUM(E, ...) \
    enum E { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, __VA_ARGS__)

#define BOOST_DEFINE_ENUM_CLASS(E, ...) \
    enum class E { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM_CLASS(E, __VA_ARGS__)

#define BOOST_DEFINE_FIXED_ENUM(E, Base, ...) \
    enum E: Base { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM(E, __VA_ARGS__)

#define BOOST_DEFINE_FIXED_ENUM_CLASS(E, Base, ...) \
    enum class E: Base { __VA_ARGS__ }; BOOST_DESCRIBE_ENUM_CLASS(E, __VA_ARGS__)
```

### BOOST_DESCRIBE_ENUM

`BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)` should be placed in the namespace
where the enumeration type `E` is defined, and creates the necessary metadata
for `describe_enumerators<E>` to work.

After this macro is used, `describe_enumerators<E>` returns `L<D1, D2, ..., Dn>`,
where `L` is a class template of the form
```
template<class...> struct L {};
```
and `Di` is an _enumerator descriptor_ of the form
```
struct Di
{
    static constexpr E value = vi;
    static constexpr char const * name = "vi";
};
```
where `vi` is the corresponding identifier passed to the macro.

### BOOST_DESCRIBE_NESTED_ENUM

`BOOST_DESCRIBE_NESTED_ENUM(E, v1, v2, ..., vN)` is similar to
`BOOST_DESCRIBE_ENUM` and is used to annotate enumeration types nested inside
class (or `struct`) types. It should be placed in the class type where the
`enum` is defined.

### BOOST_DEFINE_ENUM

`BOOST_DEFINE_ENUM(E, v1, v2, ..., vN)` is a convenience macro expanding to
```
enum E { v1, v2, ..., vN };
BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)
```

### BOOST_DEFINE_ENUM_CLASS

`BOOST_DEFINE_ENUM_CLASS(E, v1, v2, ..., vN)` is a convenience macro expanding to
```
enum class E { v1, v2, ..., vN };
BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)
```

### BOOST_DEFINE_FIXED_ENUM

`BOOST_DEFINE_FIXED_ENUM(E, Base, v1, v2, ..., vN)` is a convenience macro expanding to
```
enum E: Base { v1, v2, ..., vN };
BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)
```

### BOOST_DEFINE_FIXED_ENUM_CLASS

`BOOST_DEFINE_FIXED_ENUM_CLASS(E, Base, v1, v2, ..., vN)` is a convenience macro expanding to
```
enum class E: Base { v1, v2, ..., vN };
BOOST_DESCRIBE_ENUM(E, v1, v2, ..., vN)
```

## <boost/describe/{zwsp}enumerators{zwsp}.hpp>

```
namespace boost {
namespace describe {

template<class E> using describe_enumerators = /*...*/;

template<class E> using has_describe_enumerators = /*...*/;

} }
```

### describe_enumerators<E>

`describe_enumerators<E>` returns `L<D1, D2, ..., Dn>`, where `L` is a class
template of the form
```
template<class...> struct L {};
```
and `Di` is an _enumerator descriptor_ of the form
```
struct Di
{
    static constexpr E value = vi;
    static constexpr char const * name = "vi";
};
```
where `vi` is the i-th enumerator.

If `E` is not a described enumeration type, `describe_enumerators<E>` causes
a substitution failure.

### has_describe_enumerators<E>

`has_describe_enumerators<E>::value` is `true` when `E` is a described
enumeration type, `false` otherwise.

## <boost/describe/class.hpp>

```
#define BOOST_DESCRIBE_STRUCT(Name, Bases, Members) /*...*/
#define BOOST_DESCRIBE_CLASS(Name, Bases, Public, Protected, Private) /*...*/
```

### BOOST_DESCRIBE_STRUCT

`BOOST_DESCRIBE_STRUCT` should be placed in the same namespace as the struct
type being described, and takes three arguments: name of the struct type,
a parentheses-enclosed list of base classes, and a parentheses-enclosed list
of public members.

Example:
```
struct X
{
};

BOOST_DESCRIBE_STRUCT(X, (), ())

struct Y: public X
{
    int m;
    static void f();
};

BOOST_DESCRIBE_STRUCT(Y, (X), (m, f))
```

### BOOST_DESCRIBE_CLASS

`BOOST_DESCRIBE_CLASS` should be placed inside the class definition of the
described type, and takes five arguments: the name of the class, a list of
base classes, a list of public members, a list of protected members, and a
list of private members.

Example:
```
class X
{
    int m1;

    BOOST_DESCRIBE_CLASS(X, (), (), (), (m1))
};

class Y: private X
{
public:

    int m1;
    void f() const {}

protected:

    int m2;

private:

    int m3;

    BOOST_DESCRIBE_CLASS(Y, (X), (m1, f), (m2), (m3))
};
```

## <boost/describe/modifiers.hpp>

```
namespace boost
{
namespace describe
{

enum modifiers
{
    mod_public = 1,
    mod_protected = 2,
    mod_private = 4,
    mod_virtual = 8,
    mod_static = 16,
    mod_function = 32,
    mod_any_member = 64,
    mod_inherited = 128,
    mod_hidden = 256
};

constexpr modifiers mod_any_access = static_cast<modifiers>( mod_public | mod_protected | mod_private );

} // namespace describe
} // namespace boost
```

### modifiers

The enumeration type `modifiers` is a bitmask type that contains the
following flags:

* `mod_public` - includes public bases or members in the descriptor list
* `mod_protected` - includes protected bases or members
* `mod_private` - includes private bases or members
* `mod_virtual` - returned when a base class is a virtual base
* `mod_static` - returns static members (when not given, returns nonstatic members)
* `mod_function` - returns member functions (when not given, returns data members)
* `mod_any_member` - overrides `mod_static` and `mod_function` and returns all members regardless of kind
* `mod_inherited` - includes members of base classes
* `mod_hidden` - includes hidden inherited members

## <boost/describe/{zwsp}modifier_description.hpp>

The header `modifier_description.hpp` includes `modifiers.hpp` and invokes
`BOOST_DESCRIBE_ENUM` on `modifiers`, allowing `describe_enumerators<modifiers>`
to work.

## <boost/describe/bases.hpp>

```
namespace boost {
namespace describe {

template<class T, unsigned M> using describe_bases = /*...*/;

template<class T> using has_describe_bases = /*...*/;

} }
```

### describe_bases<T, M>

`M` must be a bitwise-or combination of `mod_public`, `mod_protected`, and
`mod_private`, and acts as a filter.

`describe_bases<T, M>` returns `L<D1, D2, ..., Dn>`, where `L` is a class
template of the form
```
template<class...> struct L {};
```
and `Di` is a _base descriptor_ of the form
```
struct Di
{
    using type = /*...*/;
    static constexpr unsigned modifiers = /*...*/;
};
```
where `type` is the type of the base class, and `modifiers` are a bitwise-or
combination of `mod_public`, `mod_protected`, `mod_private`, and `mod_virtual`
that reflects the properties of the base class.

If `T` is not a described class type, `describe_bases<T, M>` causes a
substitution failure.

### has_describe_bases<T>

`has_describe_bases<T>::value` is `true` when `T` is a described class type,
`false` otherwise.

Since the library does not provide a way to describe bases and members separately,
`has_describe_bases` and `has_describe_members` are, in practice, synonyms. They
are provided separately for consistency.

## <boost/describe/members.hpp>

```
namespace boost {
namespace describe {

template<class T, unsigned M> using describe_members = /*...*/;

template<class T> using has_describe_members = /*...*/;

} }
```

### describe_members<T, M>

`M` must be a bitwise-or combination of `mod_public`, `mod_protected`,
`mod_private`, `mod_static`, `mod_function`, `mod_any_member`,
`mod_inherited`, and `mod_hidden`, and acts as a filter.

`describe_members<T, M>` returns `L<D1, D2, ..., Dn>`, where `L` is a class
template of the form
```
template<class...> struct L {};
```
and `Di` is a _member descriptor_ of the form
```
struct Di
{
    static constexpr auto pointer = &T::m;
    static constexpr char const * name = "m";
    static constexpr unsigned modifiers = /*...*/;
};
```
where `pointer` is a pointer to member (for nonstatic members) or a pointer
(for static members) identifying the class member, `name` is the name of the
member, and `modifiers` are a bitwise-or combination of `mod_public`,
`mod_protected`, `mod_private`, `mod_static`, `mod_function`, `mod_inherited`,
and `mod_hidden` that reflects the properties of the member.

If `T` is not a described class type, `describe_members<T, M>` causes a
substitution failure.

### has_describe_members<T>

`has_describe_members<T>::value` is `true` when `T` is a described class type,
`false` otherwise.

Since the library does not provide a way to describe bases and members separately,
`has_describe_bases` and `has_describe_members` are, in practice, synonyms. They
are provided separately for consistency.

## <boost/describe/{zwsp}enum_to_string{zwsp}.hpp>

```
namespace boost {
namespace describe {

template<class E> char const * enum_to_string( E e, char const * def ) noexcept;

} }
```

### enum_to_string

The function `enum_to_string` returns the name of the enumerator `e`. `E` must
be a described enumeration type. If `e` does not correspond to one of the described
values, the function returns `def`.

## <boost/describe/{zwsp}enum_from_string{zwsp}.hpp>

```
namespace boost {
namespace describe {

template<class E> bool enum_from_string( char const * name, E & e ) noexcept;
template<class S, class E> bool enum_from_string( S const & name, E & e ) noexcept;

} }
```

### enum_from_string

The function `enum_from_string` assigns to `e` the enumerator value corresponding
to `name` and returns `true`. `E` must be a described enumeration type. If `name`
does not correspond to one of the described values, the function returns `false`.

The second overload only participates in overload resolution when `S` is a
string-like type such as `std::string` or `std::string_view`. String-like types
are recognized by the presence of nested `value_type` and `traits_type` typedefs
and are expected to have a non-throwing `operator==` taking `char const*`.

## <boost/describe/operators.hpp>

```
namespace boost {
namespace describe {
namespace operators {

template<class T> bool operator==( T const& t1, T const& t2 );
template<class T> bool operator!=( T const& t1, T const& t2 );
template<class T> bool operator<( T const& t1, T const& t2 );
template<class T> bool operator>( T const& t1, T const& t2 );
template<class T> bool operator<=( T const& t1, T const& t2 );
template<class T> bool operator>=( T const& t1, T const& t2 );

template<class T, class Ch, class Tr>
  std::basic_ostream<Ch, Tr>&
    operator<<( std::basic_ostream<Ch, Tr>& os, T const& t );

} } }
```

The header `<boost/describe/operators.hpp>` defines generic operators for
described class types. They are used by bringing them into the namespace
containing the described types via a using declaration, as in the example
below:

```
namespace app
{

struct X
{
    int a = 1;
};

BOOST_DESCRIBE_STRUCT(X, (), (a))

using boost::describe::operators::operator==;
using boost::describe::operators::operator!=;
using boost::describe::operators::operator<<;

}
```

### operator==

If all bases and members compare equal, returns `true`, otherwise `false`.

### operator!=

Returns the negation of `operator==`.

### operator<

Performs a lexicographical comparison over the bases and members in sequence
using `operator<` and returns the result.

### operator>

Returns the result of `operator<` with the arguments reversed.

### operator\<=

Returns the negated result of `operator>`.

### operator>=

Returns the negated result of `operator<`.

### operator<<

Outputs a representation of `t` to `os` by recursively using `operator<<`
to output all bases and then all members.

## <boost/describe/{zwsp}descriptor_by_name{zwsp}.hpp>

```
namespace boost {
namespace describe {

#define BOOST_DESCRIBE_MAKE_NAME(s) /*...*/

template<class L, class N> using descriptor_by_name = /*...*/;

} }
```

### BOOST_DESCRIBE_MAKE_NAME

The macro `BOOST_DESCRIBE_MAKE_NAME` creates a type that identifies the
name given as an argument. It should be used as follows:

```
using N = BOOST_DESCRIBE_MAKE_NAME(some_member);
```

### descriptor_by_name

`descriptor_by_name<L, N>` searches the descriptor list `L` for the member
with the name identified by `N`. `N` should be a type created by
`BOOST_DESCRIBE_MAKE_NAME` as in the above example. `L` is intended to be
a list returned by `describe_members`, although since enumerator descriptors
also have `::name`, a list returned by `describe_enumerators` will work as
well.

.Using descriptor_by_name
```
using L = describe_members<SomeType, mod_any_access>;
using N = BOOST_DESCRIBE_MAKE_NAME(some_member);
using D = descriptor_by_name<L, N>; // descriptor for SomeType::some_member
```

## <boost/describe/{zwsp}descriptor_by_pointer{zwsp}.hpp>

```
namespace boost {
namespace describe {

template<class L, auto Pm> using descriptor_by_pointer = /*...*/;

} }
```

### descriptor_by_pointer

`descriptor_by_pointer<L, Pm>` searches the descriptor list `L` for the member
pointer `Pm`. `L` should be a list returned by `describe_members`.

Since `auto` template parameters are a {cpp}17 feature, using
`descriptor_by_pointer` requires {cpp}17.

.Using descriptor_by_pointer
```
using L = describe_members<X, mod_any_access>;
using D = descriptor_by_pointer<L, &X::a>; // descriptor for X::a
```

## <boost/describe.hpp>

This convenience header includes all the headers previously
described.
