Loading...
Searching...
No Matches
Classes | Namespaces | Macros | Typedefs | Functions | Variables
reflection.h File Reference

Compile-time reflection of: More...

#include "util/tuple.h"
#include "util/named.h"
#include "util/macro_util.h"
#include "util/string_literal.h"
#include "concepts/reflection.h"

Go to the source code of this file.

Classes

struct  prefix< N, C >
 Wrapper for adding a prefix to the attribute names of a base type. More...
 

Namespaces

namespace  bbm
 
namespace  bbm::reflection
 

Macros

#define BBM_ATTRIBUTES(...)
 BBM_ATTRIBUTES macro for declaring the attriute of a class.
 
#define BBM_ATTRIBUTES_T   std::conditional_t<attribute_tuple_t::size == 0, typename reflection_base_t::attribute_tuple_t, attribute_tuple_t>
 BBM_ATTRIBUTES_T macro for robustly obtaining the type of the attributes tuple in unevaluated context.
 
#define BBM_BASETYPES(...)   using reflection_base_t = bbm::reflection::detail::base_types<__VA_ARGS__>;
 BaseTypes macro for declaring the base types/classes of a class.
 
#define BBM_ENUM(FlagName, ...)
 BBM_ENUM macro for declaring the types of an enum.
 

Typedefs

template<typename T >
using attributes_t = typename bbm::reflection::detail::attributes_impl< T >::type
 
Global aliases.

Fallback for classes when no BaseTypes or Attributes are defined. The reason for a global alias is because decltype(*this) cannot be used in an unevaluated context (i.e., attribute_tuple_t in Attributes(...).

using reflection_base_t = bbm::reflection::detail::base_types<>
 
using attribute_tuple_t = reflection_base_t::attribute_tuple_t
 

Functions

template<typename T >
constexpr decltype(auto) attributes (T &&t)
 

Variables

template<typename T >
static constexpr size_t attributes_size = std::tuple_size< attributes_t<T> >::value
 
template<typename T >
static constexpr auto enum_v = bbm_enum<std::decay_t<T>>::values()
 Querry the names and values of an enum.
 

BaseTypes reflection methods

template<typename C >
using basetypes_t = typename bbm::reflection::detail::basetypes_impl< C >::type
 
template<typename C >
static constexpr size_t basetypes_size = std::tuple_size< basetypes_t<C> >::value
 

Detailed Description

Compile-time reflection of:

To do:

Usage:

To add attribute reflection, add 'BBM_ATTRIBUTES(<attribute names...>)' after the declaration of the class attributes. For example:

struct foo
{
floar bar;
char var;
BBM_ATTRIBUTES(bar, var);
};
#define BBM_ATTRIBUTES(...)
BBM_ATTRIBUTES macro for declaring the attriute of a class.
Definition: reflection.h:141

We can then query the attributes, types, and number of attributes:

foo f{1,'a'};
std::cout << attributes(f) << std::endl; // (bar = 1, var = 'a')
std::cout << typestring< attributes_t<foo> > << std::endl; // named< std::tuple<float&, char&>, "bar", "var" >
std::cout << attributes_size<foo> << std::endl; // 2
std::cout << typestring< std::tuple_element_t<0, attributes_t<foo>>> << std::endl; // float

Note: we can also pass the attributes of an attribute; the name will be the names of the attributes of of the attribue:

struct foo2
{
float a;
foo b;
BBM_ATTRIBUTES(a, attributes(b));
};
foo2 f2;
std::cout << attributes(f2) << std::endl; // (a=0, bar=0, var=0)

To add public base class reflection, add 'BBM_BASETYPES(<base class names...>)' at the start of the class. For example:

struct foo2 : public foo
{
foo2(float a, float b, char c) : bar2(a), bar(b), var(c) {}
float bar2;
}
#define BBM_BASETYPES(...)
BaseTypes macro for declaring the base types/classes of a class.
Definition: reflection.h:215

To querry the type of the return type of attributes(...):

struct foo3
{
float a, b;
using A = BBM_ATTRIBUTES_T; // bbm::named<std::tuple<float,float>, "a", "b">
};
using B = attributes_t<foo3>; // bbm::named<std::tuple<float,float>, "a", "b">
#define BBM_ATTRIBUTES_T
BBM_ATTRIBUTES_T macro for robustly obtaining the type of the attributes tuple in unevaluated context...
Definition: reflection.h:161

The difference between both (A and B) is that B requires an evaluated context (i.e., the type of the class must be known), whereas A is robust in unevaluated contexts (i.e., from inside the class before the class is complete).

We can query the base classes:

std::cout << typestring< std::tuple_element_t< 0, basetypes_t<foo2> > > << std::endl; // foo
std::cout << basetypes_size<foo2> << std::endl; // 1

Querying the attributes will include the attributes of the base class too:

std::cout << attributes(f2) << std::endl; // (bar2 = 3, bar = 1, var = 'a')

In some cases it might be desirable to prefix the attribute names of a base class:

struct foo3 : public foo, foo2
{
BBM_BASETYPES(prefix<"foo::", foo>, foo2);
foo3(float a, float b, char c) : foo(13,'b'), foo2(a,b,c) {}
};
foo3 f3(3,1,'a');
std::cout << attributes(f3) << std::endl; // (foo::bar = 13, foo::var = 'b', bar2 = 3, bar = 1, var = 'a')
constexpr decltype(auto) attributes(T &&t)
Definition: reflection.h:200

BBM also support reflection for enum struct/classes.

enum struct foo { A, B, C };
BBM_ENUM(foo, A, B, C);
std::cout << bbm::get<"B">(enum_v<foo>) << std::endl; // 1
std::cout << bbm::get<1>(enum_v<foo>) << std::endl; // 1
std::cout << enum_v<foo>[1] << std::endl; // 1
std::cout << enum_v<foo>.template name<1> << std::endl; // "B"
constexpr decltype(auto) get(T &&src)
Definition: named.h:317
#define BBM_ENUM(FlagName,...)
BBM_ENUM macro for declaring the types of an enum.
Definition: reflection.h:332

See concepts/reflection.h for reflection related concepts.


Class Documentation

◆ bbm::reflection::prefix

struct bbm::reflection::prefix
template<string_literal N, typename C>
struct bbm::reflection::prefix< N, C >

Wrapper for adding a prefix to the attribute names of a base type.

Macro Definition Documentation

◆ BBM_ATTRIBUTES

#define BBM_ATTRIBUTES (   ...)
Value:
\
inline constexpr auto attribute_tuple(void) \
{ \
auto attr = bbm::named_flatten(bbm::make_named<BBM_STRINGIFY_EACH(__VA_ARGS__)>(bbm::make_ref_tuple(__VA_ARGS__))); \
return bbm::named_cat(attr, reflection_base_t::attribute_tuple(*this)); \
} \
\
inline constexpr auto attribute_tuple(void) const \
{ \
auto attr = bbm::named_flatten(bbm::make_named<BBM_STRINGIFY_EACH(__VA_ARGS__)>(bbm::make_ref_tuple(__VA_ARGS__))); \
return bbm::named_cat(attr, reflection_base_t::attribute_tuple(*this)); \
} \
#define BBM_STRINGIFY_EACH(...)
Expand VA_ARGS before converting to a comma separated series strings of elements.
Definition: macro_util.h:81
constexpr auto named_cat(T &&... t)
cat named types
Definition: named_util.h:40
constexpr named< anonymize_t< T >, NAMES... > make_named(T &&t)
Make a named of a gettable type (with size == #NAMES); renames if the type is a named container.
Definition: named.h:293
constexpr auto make_ref_tuple(ARGS &&... args)
Make a tuple of references.
Definition: tuple.h:46
constexpr auto named_flatten(T &&t)
flatten a named type without merging names
Definition: named_util.h:170
decltype(named_cat(std::declval< T >()...)) named_cat_t
type of concatting multiple named tuples.
Definition: named_util.h:56
named container
Definition: named.h:131

BBM_ATTRIBUTES macro for declaring the attriute of a class.

◆ BBM_ATTRIBUTES_T

#define BBM_ATTRIBUTES_T   std::conditional_t<attribute_tuple_t::size == 0, typename reflection_base_t::attribute_tuple_t, attribute_tuple_t>

BBM_ATTRIBUTES_T macro for robustly obtaining the type of the attributes tuple in unevaluated context.

◆ BBM_BASETYPES

#define BBM_BASETYPES (   ...)    using reflection_base_t = bbm::reflection::detail::base_types<__VA_ARGS__>;

BaseTypes macro for declaring the base types/classes of a class.

◆ BBM_ENUM

#define BBM_ENUM (   FlagName,
  ... 
)
Value:
template<> struct bbm::reflection::bbm_enum<FlagName> \
{ \
static constexpr auto values(void) \
{ \
using enum FlagName; \
return bbm::make_named<BBM_STRINGIFY_EACH(__VA_ARGS__)>( std::array{ __VA_ARGS__ } ); \
} \
}; \
Definition: reflection.h:18

BBM_ENUM macro for declaring the types of an enum.

Typedef Documentation

◆ attribute_tuple_t

◆ reflection_base_t

using reflection_base_t = bbm::reflection::detail::base_types<>