Overview

This library enables authors of user-defined types (enums, structs and classes) to describe their enumerators, base classes, data members and member functions. This information can later be queried by other code portions, possibly written by a different author, using the supplied primitives describe_enumerators, describe_bases, and describe_members.

To learn how to describe enumeration types, see Describing Enumeration Types.

To learn how to describe class types, including structs, see Describing Class Types.

For examples how this functionality is useful, see Usage Examples.

The purpose of the library is to establish a standard way of providing these reflection abilities. Many existing libraries provide their own way of describing enums or classes, but without a standard, code written by different people cannot interoperate.

Eventually, one might hope for the primitives to end up in the C++ standard, with the compiler automatically supplying the metadata necessary to describe the types, making manual macro annotation unnecessary.

Describing Enumeration Types

If you have an enumeration type

enum E
{
    v1 = 1,
    v2 = 2,
    v3 = 4,
};

you can add reflection metadata to it via the BOOST_DESCRIBE_ENUM macro:

BOOST_DESCRIBE_ENUM(E, v1, v2, v3)

The macro is defined in <boost/describe/enum.hpp> and should be placed in the same namespace as the enum.

For scoped enums, use BOOST_DESCRIBE_ENUM_CLASS instead.

If your enumerators don’t have initializers, instead of repeating them

enum E2 { a, b, c, d };
BOOST_DESCRIBE_ENUM(E2, a, b, c, d)

you can use the convenience macro

BOOST_DEFINE_ENUM(E2, a, b, c, d)

which expands to the two previous lines.

For defining enum class E2 instead, use BOOST_DEFINE_ENUM_CLASS. To add an underlying type, i.e. enum E3: int or enum class E4: unsigned char, use BOOST_DEFINE_FIXED_ENUM and BOOST_DEFINE_FIXED_ENUM_CLASS, respectively.

Once an enumeration type E is annotated, one can use describe_enumerators<E> to obtain a descriptor list. (describe_enumerators is defined in the boost::describe namespace, in <boost/describe/enumerators.hpp>.)

A descriptor list is a type of the form L<D1, D2, …​, Dn>, where L is of the form template<class…​ T> struct L {}; and Di is of the form

struct Di
{
    static constexpr E value;
    static constexpr char const* name;
};

To iterate over the descriptor list, you can use mp_for_each from Mp11:

boost::mp11::mp_for_each< boost::describe::describe_enumerators<E> >([](auto D){

    std::printf( "%s: %d\n", D.name, D.value );

});

Describing Class Types

If you have a struct

struct X
{
    int m1;
    int m2;
};

use the BOOST_DESCRIBE_STRUCT macro to describe it:

BOOST_DESCRIBE_STRUCT(X, (), (m1, m2))

BOOST_DESCRIBE_STRUCT is defined in <boost/describe/class.hpp> and should be placed in the same namespace as the struct.

It takes three arguments: the struct name, a list of base classes (empty in our example), and a list of (public) members by name (this includes both data members and member functions.)

To describe a class type with protected or private members, use the BOOST_DESCRIBE_CLASS macro instead, placing it inside the class.

class Y: private X
{
public:

    int m3;

protected:

    int m4;

private:

    int m5;

public:

    int f() const;

private:

    BOOST_DESCRIBE_CLASS(Y, (X), (m3, f), (m4), (m5))
};

It takes three member lists, for the public, protected, and private members.

Once a type T is annotated, its properties can be retrieved via describe_bases<T, M> and describe_members<T, M> (M is a bitmask of modifiers such as mod_public | mod_static | mod_function).

These primitives are defined in namespace boost::describe, in the headers <boost/describe/bases.hpp> and <boost/describe/members.hpp>, respectively.

describe_bases takes the following possible modifiers: mod_public, mod_protected, mod_private, or a bitwise-or combination of them. The presence of mod_public includes the public bases in the result, its absence excludes them. The other two modifiers work similarly.

(At least in principle. The current implementation cannot distinguish between protected and private base classes, so protected bases are returned as private. Consequently, using mod_protected gives no result. Lifting this limitation would require compiler support.)

describe_members takes a bitwise-or combination of the following possible modifiers: mod_public, mod_protected, mod_private, mod_static, mod_function, mod_inherited, mod_hidden.

The access modifiers work the same as with describe_bases (except here mod_protected actually works when BOOST_DESCRIBE_CLASS is used.)

(For types annotated with BOOST_DESCRIBE_STRUCT, the protected and private member lists will be empty.)

When mod_static is present, the static members are returned, otherwise the nonstatic members are returned.

When mod_function is present, the member functions are returned, otherwise the data members are returned.

When mod_inherited is present, members of base classes are also returned.

When mod_hidden is present, hidden inherited members are included. A member of a base class is hidden when a derived class has a member of the same name.

For the above class Y, describe_bases<Y, mod_any_access> will return a type list L<D1> containing a single base descriptor D1 describing X:

struct D1
{
    using type = X;
    static constexpr unsigned modifiers = mod_private;
};

describe_members<Y, mod_private> will return a type list L<D2> containing the descriptor of the data member Y::m5:

struct D2
{
    static constexpr int Y::* pointer = &Y::m5;
    static constexpr char const * name = "m5";
    static constexpr unsigned modifiers = mod_private;
};

For an example of how to use the base and data member descriptors, see Defining a Universal Print Function.

For an example of how to use member function descriptors, see Automatic JSON RPC.

Usage Examples

Printing Enumerators with a Compile Time Loop

A simple example that just iterates over the enumerator descriptors using mp11::mp_for_each and prints them.

#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <cstdio>

enum E
{
    v1 = 11,
    v2,
    v3 = 5
};

BOOST_DESCRIBE_ENUM(E, v1, v2, v3)

int main()
{
    boost::mp11::mp_for_each< boost::describe::describe_enumerators<E> >([](auto D){

        std::printf( "%s: %d\n", D.name, D.value );

    });
}

Printing Enumerators with a Run Time Loop

This is similar to the previous example, but it first builds a std::array with the values, and then iterates over it using an ordinary for loop, instead of mp_for_each.

#include <boost/describe.hpp>
#include <cstdio>
#include <array>

template<class E> struct enum_descriptor
{
    E value;
    char const * name;
};

template<class E, template<class... T> class L, class... T>
  constexpr std::array<enum_descriptor<E>, sizeof...(T)>
    describe_enumerators_as_array_impl( L<T...> )
{
    return { { { T::value, T::name }... } };
}

template<class E> constexpr auto describe_enumerators_as_array()
{
    return describe_enumerators_as_array_impl<E>( boost::describe::describe_enumerators<E>() );
}

BOOST_DEFINE_ENUM(E, v1, v2, v3, v4, v5, v6)

int main()
{
    constexpr auto D = describe_enumerators_as_array<E>();

    for( auto const& x: D )
    {
        std::printf( "%s: %d\n", x.name, x.value );
    }
}

enum_to_string

This example shows a function that, given an enumerator value, returns its name.

Providing enum_to_string in a library is made difficult by the fact that the desired behavior when the passed value does not correspond to a named enumerator varies depending on the specific use case. But, since defining the function is trivial when describe_enumerators is available, every user can easily have his own.

This specific example elects to return "(unnamed)" when the enum value doesn’t have a name.

#include <boost/describe.hpp>
#include <boost/mp11.hpp>

template<class E> char const * enum_to_string( E e )
{
    char const * r = "(unnamed)";

    boost::mp11::mp_for_each< boost::describe::describe_enumerators<E> >([&](auto D){

        if( e == D.value ) r = D.name;

    });

    return r;
}

#include <iostream>

enum E
{
    v1 = 3,
    v2,
    v3 = 11
};

BOOST_DESCRIBE_ENUM(E, v1, v2, v3)

int main()
{
    std::cout << "E(" << v1 << "): " << enum_to_string( v1 ) << std::endl;
    std::cout << "E(" << 0 << "): " << enum_to_string( E(0) ) << std::endl;
}

string_to_enum

The opposite of the previous example; returns an enumerator value when given the enumerator name. The same problem exists here with respect to the error handling strategy when the string passed does not correspond to any enumerator name. This example throws an exception.

#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <stdexcept>
#include <typeinfo>
#include <string>
#include <cstring>

[[noreturn]] void throw_invalid_name( char const * name, char const * type )
{
    throw std::runtime_error(
        std::string( "Invalid enumerator name '" ) + name + "' for enum type '" + type + "'" );
}

template<class E> E string_to_enum( char const * name )
{
    bool found = false;
    E r = {};

    boost::mp11::mp_for_each< boost::describe::describe_enumerators<E> >([&](auto D){

        if( !found && std::strcmp( D.name, name ) == 0 )
        {
            found = true;
            r = D.value;
        }

    });

    if( found )
    {
        return r;
    }
    else
    {
        throw_invalid_name( name, typeid( E ).name() );
    }
}

#include <iostream>

BOOST_DEFINE_ENUM(E, v1, v2, v3)

int main()
{
    try
    {
        std::cout << "v1: " << string_to_enum<E>( "v1" ) << std::endl;
        std::cout << "v2: " << string_to_enum<E>( "v2" ) << std::endl;
        std::cout << "v3: " << string_to_enum<E>( "v3" ) << std::endl;
        std::cout << "v4: " << string_to_enum<E>( "v4" ) << std::endl;
    }
    catch( std::exception const & x )
    {
        std::cout << x.what() << std::endl;
    }
}

Defining a Universal Print Function

This example defines a universal operator<< that works on any class or struct type that has been described with BOOST_DESCRIBE_STRUCT or BOOST_DESCRIBE_CLASS.

It first prints the base classes, recursively, then prints all the members.

(A C cast is used to access private base classes. This is not as bad as it first appears, because we’re only inspecting the base class by printing its members, and doing so should not change its state and hence cannot violate its invariant.)

#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <ostream>

using namespace boost::describe;

template<class T,
    class Bd = describe_bases<T, mod_any_access>,
    class Md = describe_members<T, mod_any_access>>
    std::ostream& operator<<( std::ostream & os, T const & t )
{
    os << "{";

    bool first = true;

    boost::mp11::mp_for_each<Bd>([&](auto D){

        if( !first ) { os << ", "; } first = false;

        using B = typename decltype(D)::type;
        os << (B const&)t;

    });

    boost::mp11::mp_for_each<Md>([&](auto D){

        if( !first ) { os << ", "; } first = false;

        os << "." << D.name << " = " << t.*D.pointer;

    });

    os << "}";
    return os;
}

struct X
{
    int m1 = 1;
};

BOOST_DESCRIBE_STRUCT(X, (), (m1))

struct Y
{
    int m2 = 2;
};

BOOST_DESCRIBE_STRUCT(Y, (), (m2))

class Z: public X, private Y
{
    int m1 = 3;
    int m2 = 4;

    BOOST_DESCRIBE_CLASS(Z, (X, Y), (), (), (m1, m2))
};

#include <iostream>

int main()
{
    std::cout << Z() << std::endl;
}

Automatic Conversion to JSON

This example defines a universal tag_invoke overload that automatically converts an annotated struct to a Boost.JSON value by iterating over the described public members and adding them to the return boost::json::object.

The overload is defined in namespace app in order to apply to all annotated classes also defined in app.

The presence of private members is taken as an indication that a universal conversion is not suitable, so the overload is disabled in this case using std::enable_if_t.

#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/json.hpp>
#include <type_traits>
#include <vector>
#include <map>

namespace app
{

template<class T,
    class D1 = boost::describe::describe_members<T,
        boost::describe::mod_public | boost::describe::mod_protected>,
    class D2 = boost::describe::describe_members<T, boost::describe::mod_private>,
    class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value> >

    void tag_invoke( boost::json::value_from_tag const&, boost::json::value& v, T const & t )
{
    auto& obj = v.emplace_object();

    boost::mp11::mp_for_each<D1>([&](auto D){

        obj[ D.name ] = boost::json::value_from( t.*D.pointer );

    });
}

struct A
{
    int x;
    int y;
};

BOOST_DESCRIBE_STRUCT(A, (), (x, y))

struct B
{
    std::vector<A> v;
    std::map<std::string, A> m;
};

BOOST_DESCRIBE_STRUCT(B, (), (v, m))

} // namespace app

#include <iostream>

int main()
{
    app::B b{ { { 1, 2 }, { 3, 4 } }, { { "k1", { 5, 6 } }, { "k2", { 7, 8 } } } };

    std::cout << boost::json::value_from( b ) << std::endl;
}

Automatic Conversion from JSON

Like the previous example, but in the other direction. Defines a tag_invoke overload that converts a boost::json::value to an annotated struct.

#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/json.hpp>
#include <type_traits>

namespace app
{

template<class T> void extract( boost::json::object const & obj, char const * name, T & value )
{
    value = boost::json::value_to<T>( obj.at( name ) );
}

template<class T,
    class D1 = boost::describe::describe_members<T,
        boost::describe::mod_public | boost::describe::mod_protected>,
    class D2 = boost::describe::describe_members<T, boost::describe::mod_private>,
    class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value> >

    T tag_invoke( boost::json::value_to_tag<T> const&, boost::json::value const& v )
{
    auto const& obj = v.as_object();

    T t{};

    boost::mp11::mp_for_each<D1>([&](auto D){

        extract( obj, D.name, t.*D.pointer );

    });

    return t;
}

struct A
{
    int x;
    int y;
};

BOOST_DESCRIBE_STRUCT(A, (), (x, y))

} // namespace app

#include <iostream>

int main()
{
    boost::json::value jv{ { "x", 1 }, { "y", 2 } };

    std::cout << "jv: " << jv << std::endl;

    auto a = boost::json::value_to<app::A>( jv );

    std::cout << "a: { " << a.x << ", " << a.y << " }" << std::endl;
}

Automatic Serialization

This example defines a universal serialize function that automatically adds Boost.Serialization support to annotated classes.

#define _CRT_SECURE_NO_WARNINGS

#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/core/nvp.hpp>
#include <type_traits>
#include <cstdio>
#include <vector>

namespace app
{

template<class Archive, class T,
    class D1 = boost::describe::describe_bases<T, boost::describe::mod_public>,
    class D2 = boost::describe::describe_bases<T,
        boost::describe::mod_protected | boost::describe::mod_private>,
    class D3 = boost::describe::describe_members<T,
        boost::describe::mod_public | boost::describe::mod_protected>,
    class D4 = boost::describe::describe_members<T, boost::describe::mod_private>,
    class En = std::enable_if_t<
        boost::mp11::mp_empty<D2>::value && boost::mp11::mp_empty<D4>::value> >

    void serialize( Archive & ar, T & t, boost::serialization::version_type )
{
    int k = 0;

    // public bases: use base_object

    boost::mp11::mp_for_each<D1>([&](auto D){

        using B = typename decltype(D)::type;

        char name[ 32 ];
        std::sprintf( name, "base.%d", ++k );

        ar & boost::make_nvp( name, boost::serialization::base_object<B>( t ) );

    });

    // public (and protected) members

    boost::mp11::mp_for_each<D3>([&](auto D){

        ar & boost::make_nvp( D.name, t.*D.pointer );

    });
}

struct A1
{
    int x;
};

BOOST_DESCRIBE_STRUCT(A1, (), (x))

struct A2
{
    int y;
};

BOOST_DESCRIBE_STRUCT(A2, (), (y))

struct B: public A1, public A2
{
    // these constructors aren't needed in C++17
    B(): A1(), A2() {}
    B( int x, int y ): A1{ x }, A2{ y } {}
};

BOOST_DESCRIBE_STRUCT(B, (A1, A2), ())

struct C
{
    std::vector<B> v;
};

BOOST_DESCRIBE_STRUCT(C, (), (v))

} // namespace app

#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <string>
#include <sstream>
#include <iostream>

int main()
{
    app::C c1{ { { 1, 2 }, { 3, 4 }, { 5, 6 } } };

    std::ostringstream os;

    {
        boost::archive::xml_oarchive ar( os );
        ar << boost::make_nvp( "c1", c1 );
    }

    std::string s = os.str();

    std::cout << s << std::endl;

    app::C c2;

    {
        std::istringstream is( s );
        boost::archive::xml_iarchive ar( is );
        ar >> boost::make_nvp( "c2", c2 );
    }

    {
        boost::archive::text_oarchive ar( std::cout );
        ar << c2;
    }
}

Automatic JSON RPC

This example defines a generic call function that can be used to invoke a member function by name, with the arguments passed in a Boost.JSON array. The result is returned in a boost::json::value.

#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/json.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility/string_view.hpp>
#include <stdexcept>
#include <string>

template<class C1, class C2, class R, class... A, std::size_t... I>
  boost::json::value
    call_impl_( C1 & c1, R (C2::*pmf)(A...), boost::json::array const & args,
      std::index_sequence<I...> )
{
    return boost::json::value_from(
      (c1.*pmf)(
        boost::json::value_to< boost::remove_cv_ref_t<A> >( args[ I ] )... ) );
}

template<class C1, class C2, class R, class... A>
  boost::json::value
    call_impl( C1 & c1, R (C2::*pmf)(A...), boost::json::array const & args )
{
    if( args.size() != sizeof...(A) )
    {
        throw std::invalid_argument( "Invalid number of arguments" );
    }

    return call_impl_( c1, pmf, args, std::index_sequence_for<A...>() );
}

template<class C>
  boost::json::value
    call( C & c, boost::string_view method, boost::json::value const & args )
{
    using Fd = boost::describe::describe_members<C,
        boost::describe::mod_public | boost::describe::mod_function>;

    bool found = false;
    boost::json::value result;

    boost::mp11::mp_for_each<Fd>([&](auto D){

        if( !found && method == D.name)
        {
            result = call_impl( c, D.pointer, args.as_array() );
            found = true;
        }

    });

    if( !found )
    {
        throw std::invalid_argument( "Invalid method name" );
    }

    return result;
}

struct Object
{
    std::string greet( std::string const & who )
    {
        return "Hello, " + who + "!";
    }

    int add( int x, int y )
    {
        return x + y;
    }
};

BOOST_DESCRIBE_STRUCT(Object, (), (greet, add))

#include <iostream>

int main()
{
    Object obj;
    std::cout << call( obj, "greet", { "world" } ) << std::endl;
    std::cout << call( obj, "add", { 1, 2 } ) << std::endl;
}

Implementation Features

Dependencies

Supported Compilers

  • GCC 5 or later with -std=gnu++14 or above

  • GCC 8 or later with -std=c++14 or above

  • Clang 3.6 or later with -std=c++14 or above

  • Visual Studio 2015, 2017, 2019

Tested on Travis and Appveyor.

Limitations

This implementation has the following limitations:

  • Protected base classes cannot be distinguished from private base classes and are considered private.

  • Overloaded member functions are not supported. Member names must be unique within the class.

  • Bitfields are not supported.

  • Anonymous unions are not supported.

  • Reference members are not supported.

Reference

<boost/describe/enum.hpp>

#define BOOST_DESCRIBE_ENUM(E, ...) /*...*/
#define BOOST_DESCRIBE_ENUM_CLASS(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_ENUM_CLASS

BOOST_DESCRIBE_ENUM_CLASS(E, v1, …​, vN) should be used instead of BOOST_DESCRIBE_ENUM when E is a scoped enumeration type, and has the same effect.

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_CLASS(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_CLASS(E, v1, v2, ..., vN)

<boost/describe/enumerators.hpp>

namespace boost {
namespace describe {

template<class E> using 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.

<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_inherited = 64,
    mod_hidden = 128,
};

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_inherited - includes members of base classes

  • mod_hidden - includes hidden inherited members

<boost/describe/bases.hpp>

namespace boost {
namespace describe {

template<class T, unsigned M> using 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.

<boost/describe/members.hpp>

namespace boost {
namespace describe {

template<class T, unsigned M> using 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_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.

<boost/describe.hpp>

This convenience header includes all the headers previously described.

This documentation is copyright 2020 Peter Dimov and is distributed under the Boost Software License, Version 1.0.