Reflection in C++Next
Anton Bikineev, 2017
Agenda
Reflection in C++Next
1. Reflection
2. Surviving proposals
• P0194R3: Static reflection
• P0590R0: A design for static reflection
3. Examples
Reflection or introspection?
Reflection in C++Next
Type introspection is the ability of a program to examine the
type or properties of an object at runtime.
Reflection is the ability of a computer program to examine,
introspect, and modify its own structure and behavior at
runtime.
(from Wikipedia)
Reflection or introspection?
Reflection in C++Next
Static type introspection is the ability of a program to examine
the type or properties of an object at compile-time.
Static reflection is the ability of a computer program to
examine, introspect, and modify its own structure and
behavior at compile-time.
Introspection? Type traits!
Reflection in C++Next
namespace std {
template <class T>
struct is_integral {
constexpr static bool value = /* */true;
};
template <class T> /* since c++14 */
constexpr bool is_integral_v = is_integral<T>::value;
template <class T>
struct add_pointer {
using type = T*;
};
template <class T>
using add_pointer_t = typename add_pointer<T>::type;
}
Introspection? Type traits!
Reflection in C++Next
template <class Archive, class T>
void load(const Archive& ar, T& t) {
if constexpr (std::is_integral_v<T>)
load_integral(ar, t);
if constexpr (std::is_floating_point_v<T>)
load_fp(ar, t);
else if constexpr (std::is_trivially_copyable_v<T>)
load_memset(ar, t);
else
load_unoptimized(ar, t);
}
Introspection? Type traits!
Reflection in C++Next
template <class T, class enable = void>
struct has_foo: std::false_type {};
template <class T>
struct has_foo<T,
std::void_t<decltype(std::declval<T>().foo())>>:
std::true_type {};
Introspection? Type traits!
Reflection in C++Next
• works only with types!
• no way to traverse members!
Reflection
Reflection in C++Next
Static reflection is the ability of a computer program to
examine, introspect, and modify its own structure and
behavior at compile-time.
Reflection
Reflection in C++Next
Static reflection is the ability of a computer program to
examine, introspect, and modify its own structure and
behavior at compile-time.
Metaprogramming definition
Reflection in C++Next
Metaprogramming is the writing of computer programs
that write or manipulate other programs (or themselves)
as their data, or that do part of the work at compile time
that would otherwise be done at run-time.
(from Wikipedia, some rev.)
C++ template metaprogramming
Reflection in C++Next
auto multiply_by_two(const std::array<int, 3>& array) {
auto result = array;
for (auto& i: result)
i *= 2;
return result;
}
std::array<int, 3> arr1{1, 2, 3};
auto arr2 = multiply_by_two(arr1);
C++ template metaprogramming
Reflection in C++Next
template <class T>
struct multiply_by_two;
template <class T, T... I>
struct multiply_by_two<std::integer_sequence<T, I...>> {
using type = std::integer_sequence<T, (I * 2)...>;
};
using seq1 = std::integer_sequence<int, 1, 2, 3>;
using seq2 = multiply_by_two<seq1>::type;
C++ constexpr metaprogramming
Reflection in C++Next
constexpr
auto multiply_by_two(const std::array<int, 3>& array) {
auto result = array;
for (auto& i: result)
i *= 2;
return result;
}
constexpr std::array<int, 3> arr1{1, 2, 3};
constexpr auto arr2 = multiply_by_two(arr1);
Reflection?
Reflection in C++Next
Reflection?
Reflection in C++Next
What we actually need…
Reflection in C++Next
struct foo {
int a;
double b;
string c;
};
struct soa_foo {
vector<int> as;
vector<double> bs;
vector<string> cs;
};
Reflection in C++Next
class Person
{
[[getter, setter]] std::string name;
[[getter, setter]] std::string email;
};
What we actually need…
Reflection in C++Next
class Person
{
[[getter, setter, serialized]] std::string name;
[[getter, setter, serialized]] std::string email;
};
What we actually need…
Reflection in C++Next
class [[polymorphically_serialized]] Person: IPerson
{
Person() { /* initializing code here */ }
[[getter, setter, serialized]] std::string name;
[[getter, setter, serialized]] std::string email;
};
What we actually need…
Study Group 7: Reflection
Reflection in C++Next
• N4428: Type property queries
- 4th revision
- date: 2015-04-08
• P0255R0: Reflection via template pack expansion
- 5th revision
- date: 2016-02-12
• P0194R3: Static reflection
- 7th revision
- date: 2017-02-06
• P0590R0: A design for static reflection
- 1st revision
- date: 2017-02-05
Study Group 7: Reflection
Reflection in C++Next
• N4428: Type property queries
- 4th revision
- date: 2015-04-08
• P0255R0: Reflection via template pack expansion
- 5th revision
- date: 2016-02-12
• P0194R3: Static reflection
- 7th revision
- date: 2017-02-06
• P0590R0: A design for static reflection
- 1st revision
- date: 2017-02-05
Static reflection (P0194R3)
Reflection in C++Next
by Matúš Chochlík,
Axel Naumann,
David Sankel
P0194R3: Static reflection
Reflection in C++Next
• core-language changes:
- operator $reflect(x);
- where x is an id-expression;
- returns a unique generated type for an entity x;
- this type satisfies one or more concepts defined
in the library;
- you operate on these types (metaobjects) by
calling meta- operations.
• library changes:
- std::reflect::Concept<m>
- std::reflect::Operation<m>
P0194R3: Static reflection.
Simple example
Reflection in C++Next
std::string person = "John";
using person_m = $reflect(person);
static_assert(std::reflect::Variable<person_m>());
std::cout << std::reflect::get_base_name_v<person_m>;
P0194R3: Static reflection.
Simple example
Reflection in C++Next
std::string person = "John";
using person_m = $reflect(person);
static_assert(std::reflect::Variable<person_m>());
std::cout << std::reflect::get_base_name_v<person_m>;
using type_m = std::reflect::get_type_t<person_m>;
static_assert(std::reflect::Type<type_m>());
P0194R3: Static reflection.
Simple example
Reflection in C++Next
std::string person = "John";
using person_m = $reflect(person);
static_assert(std::reflect::Variable<person_m>());
std::cout << std::reflect::get_base_name_v<person_m>;
using type_m = std::reflect::get_type_t<person_m>;
static_assert(std::reflect::Type<type_m>());
using real_type =
std::reflect::get_reflected_type_t<type_m>;
static_assert(std::is_same_v<real_type, std::string>);
P0194R3: Static reflection.
Meta-object concepts
Reflection in C++Next
namespace std::experimental::reflect {
template <class T> concept bool Object();
template <class T> concept bool ObjectSequence();
template <Object T> concept bool Named();
template <Object T> concept bool Alias();
template <Object T> concept bool RecordMember();
template <Object T> concept bool Enumerator();
template <Object T> concept bool Variable();
template <Object T> concept bool ScopeMember();
template <Object T> concept bool Typed();
template <Object T> concept bool Namespace();
template <Object T> concept bool GlobalScope();
template <Object T> concept bool Class();
template <Object T> concept bool Enum();
template <Object T> concept bool Record();
template <Object T> concept bool Scope();
template <Object T> concept bool Type();
template <Object T> concept bool Constant();
template <Object T> concept bool Base();
}
P0194R3: Static reflection.
Class-like things
Reflection in C++Next
template <Object T> concept bool Record();
- a union or a class
template <Object T> concept bool Class();
- a class or a struct
template <Object T> concept bool Base();
- base classes
template <Object T> concept bool RecordMember();
- data member and member types
P0194R3: Static reflection.
Scopes
Reflection in C++Next
template <Object T> concept bool Namespace();
- a namespace
template <Object T> concept bool Scope();
- a namespace, class or enumeration scope
template <Object T> concept bool ScopeMember();
- something in a scope
template <Object T> concept bool GlobalScope();
- the global namespace, $reflect(::)
P0194R3: Static reflection.
Enums
Reflection in C++Next
template <Object T> concept bool Enum();
- an enum
template <Object T> concept bool Enumerator();
- an enumerator
P0194R3: Static reflection.
Types
Reflection in C++Next
template <Object T> concept bool Typed();
- something that has a type, e.g. member-variable
template <Object T> concept bool Type();
- a type
P0194R3: Static reflection.
Expressions
Reflection in C++Next
template <Object T> concept bool Variable();
- a variable
template <Object T> concept bool Constant();
- a constant-expression, like an enumerator
P0194R3: Static reflection.
Other
Reflection in C++Next
template <Object T> concept bool Named();
- something with a name;
template <Object T> concept bool Alias();
- an alias, like a typedef
template <Object T> concept bool ObjectSequence();
- object-sequence, type-list…
P0194R3:
Meta-object operations by
examples
Reflection in C++Next
P0194R3: Static reflection.
Enum-to-string
Reflection in C++Next
template <class Enum>
std::string to_string(Enum e) {
using namespace std::reflect;
using e_m = $reflect(Enum);
static_assert(std::reflect::Enum<e_m>());
std::string result;
for_each<get_enumerators_t<e_m>>([&](auto m) {
using en_m = decltype(m);
if (get_constant_v<en_m> == e)
result = get_base_name_v<en_m>;
});
return result;
}
P0194R3: Static reflection.
Generic equal
Reflection in C++Next
template <class T>
bool generic_equal(const T& a, const T& b) {
using namespace std::reflect;
using T_m = $reflect(T);
static_assert(std::reflect::Class<e_m>());
bool result = true;
for_each<get_data_members_t<T_m>>([&](auto m) {
using m_t = decltype(m);
result &= a.*get_pointer_v<m_t> ==
b.*get_pointer_v<m_t>;
});
return result;
}
P0194R3: Static reflection.
Generic equal with unreflect
Reflection in C++Next
template <class T>
bool generic_equal(const T& a, const T& b) {
using namespace std::reflect;
using T_m = $reflect(T);
static_assert(std::reflect::Class<e_m>());
bool result = true;
for_each<get_data_members_t<T_m>>([&](auto m) {
result &= a.$unreflect(m) ==
b.$unreflect(m);
});
return result;
}
P0194R3: Static reflection.
Templates parametrized by namespace
Reflection in C++Next
namespace foo {
void func1(const std::string&);
void func2(int);
int func3(int);
}
namespace bar {
void func1(const std::string&);
void func2(int);
int func3(int);
}
P0194R3: Static reflection.
Templates parametrized by namespace
Reflection in C++Next
template <class MN>
void algorithm(const string& str, int i) {
// [foo|bar]::func1(str)
$unreflect(MN)::func1(str);
// [foo|bar]::func2([foo|bar]::func3(i))
$unreflect(MN)::func2($unreflect(MN)::func3(i));
}
void func(const string& str, int i, bool want_foo) {
if (want_foo)
algorithm<$reflect(foo)>(str, i);
else
algorithm<$reflect(bar)>(str, i);
}
P0194R3: Static reflection.
String to identifier transformation
Reflection in C++Next
struct foo {
int bar;
};
constexpr const char* bar_name =
get_base_name_v<$reflect(foo::bar)>;
int get_???bar_name???(const foo&);
P0194R3: Static reflection.
String to identifier transformation
Reflection in C++Next
struct foo {
int bar;
};
constexpr const char* bar_name =
get_base_name_v<$reflect(foo::bar)>;
int $identifier(ct_concat(“get_”, bar_name))(const foo&);
P0194R3: Static reflection.
String to identifier transformation
Reflection in C++Next
struct foo {
int a;
double b;
string c;
};
struct soa_foo {
vector<int> as;
vector<double> bs;
vector<string> cs;
};
P0194R3: Static reflection
Reflection in C++Next
• supported:
- variables;
- data members;
- member types;
- enumerators;
- template instantiations;
- aliases
P0194R3: Static reflection
Reflection in C++Next
• not supported:
- declarations in namespaces (except for types);
- functions (yet);
- class templates (yet)
P0194R3: Static reflection.
Pros and cons
Reflection in C++Next
• Pros:
- reflection of different entities is supported;
- very lazy instantiation, only queried data is
instantiated;
- “you don’t pay for what you don’t use” at
compile-time;
- a good base for building higher-level and
domain-specific libraries;
- very extensible
P0194R3: Static reflection.
Pros and cons
Reflection in C++Next
• Cons:
- awkward and verbose usage;
- no attribute ideas
A design for static reflection
(P0590R0)
Reflection in C++Next
by Andrew Sutton,
Herb Sutter
P0590R0: A design for static reflection
Reflection in C++Next
• core-language changes:
- operator $x;
- where x is an id-expression;
- returns a unique object of a generated type for
an entity x;
- the object represents its meta information;
- you operate on these objects by calling
member-functions
• library changes:
- std::meta::reflection_type<X>
P0590R0: A design for static reflection.
Simple example
Reflection in C++Next
std::string person = "John";
auto person_m = $person;
static_assert(std::meta::is_variable_v<
decltype(person_m)>);
std::cout << person_m.name();
P0590R0: A design for static reflection.
Simple example
Reflection in C++Next
std::string person = "John";
auto person_m = $person;
static_assert(std::meta::is_variable_v<
decltype(person_m)>);
std::cout << person_m.name();
auto type_m = person_m.type();
static_assert(std::meta::is_type_v<decltype(type_m)>);
P0590R0: A design for static reflection.
Simple example
Reflection in C++Next
std::string person = "John";
auto person_m = $person;
static_assert(std::meta::is_variable_v<
decltype(person_m)>);
std::cout << person_m.name();
auto type_m = person_m.type();
static_assert(std::meta::is_type_v<decltype(type_m)>);
using real_type = ???;
P0194R3 vs P0590R0
Enum-to-string
Reflection in C++Next
template <class Enum>
std::string to_string(Enum e) {
using namespace std::reflect;
using e_m = $reflect(Enum);
static_assert(std::reflect::Enum<e_m>());
std::string result;
for_each<get_enumerators_t<e_m>>([&](auto m) {
using en_m = decltype(m);
if (get_constant_v<en_m> == e)
result = get_base_name_v<en_m>;
});
return result;
}
P0194R3 vs P0590R0
Enum-to-string
Reflection in C++Next
template <class Enum>
std::string to_string(Enum e) {
using namespace std::meta;
auto e_m = $Enum;
static_assert(std::meta::is_enum_v<decltype(e_m)>);
std::string result;
for_each(e_m.enumerators(), [&](auto m) {
if (m.value() == e)
result = m.name();
});
return result;
}
P0194R3 vs P0590R0
Enum-to-string
Reflection in C++Next
template <class Enum>
std::string to_string(Enum e) {
using namespace std::meta;
auto e_m = $Enum;
static_assert(std::meta::is_enum_v<decltype(e_m)>);
std::string result;
for (auto e: e_m.enumerators())
if (m.value() == e)
result = m.name();
return result;
}
P0194R3 vs P0590R0
Generic equal
Reflection in C++Next
template <class T>
bool generic_equal(const T& a, const T& b) {
bool result = true;
for (auto member: $T.member_variables()) {
auto ptr = member.pointer();
result &= a.*ptr == b.*ptr;
}
return result;
}
P0590R0: A design for static reflection.
Pros and cons
Reflection in C++Next
• Pros:
- reflection of different entities is supported;
- better syntax;
- a good base for building higher-level and
domain-specific libraries;
- extensible
P0590R0: A design for static reflection.
Pros and cons
Reflection in C++Next
• Cons:
- some extra data may still be instantiated by
compiler;
- no attribute ideas
Thank you for your attention!
Reflection in C++Next

Антон Бикинеев, Reflection in C++Next

  • 1.
  • 2.
    Agenda Reflection in C++Next 1.Reflection 2. Surviving proposals • P0194R3: Static reflection • P0590R0: A design for static reflection 3. Examples
  • 3.
    Reflection or introspection? Reflectionin C++Next Type introspection is the ability of a program to examine the type or properties of an object at runtime. Reflection is the ability of a computer program to examine, introspect, and modify its own structure and behavior at runtime. (from Wikipedia)
  • 4.
    Reflection or introspection? Reflectionin C++Next Static type introspection is the ability of a program to examine the type or properties of an object at compile-time. Static reflection is the ability of a computer program to examine, introspect, and modify its own structure and behavior at compile-time.
  • 5.
    Introspection? Type traits! Reflectionin C++Next namespace std { template <class T> struct is_integral { constexpr static bool value = /* */true; }; template <class T> /* since c++14 */ constexpr bool is_integral_v = is_integral<T>::value; template <class T> struct add_pointer { using type = T*; }; template <class T> using add_pointer_t = typename add_pointer<T>::type; }
  • 6.
    Introspection? Type traits! Reflectionin C++Next template <class Archive, class T> void load(const Archive& ar, T& t) { if constexpr (std::is_integral_v<T>) load_integral(ar, t); if constexpr (std::is_floating_point_v<T>) load_fp(ar, t); else if constexpr (std::is_trivially_copyable_v<T>) load_memset(ar, t); else load_unoptimized(ar, t); }
  • 7.
    Introspection? Type traits! Reflectionin C++Next template <class T, class enable = void> struct has_foo: std::false_type {}; template <class T> struct has_foo<T, std::void_t<decltype(std::declval<T>().foo())>>: std::true_type {};
  • 8.
    Introspection? Type traits! Reflectionin C++Next • works only with types! • no way to traverse members!
  • 9.
    Reflection Reflection in C++Next Staticreflection is the ability of a computer program to examine, introspect, and modify its own structure and behavior at compile-time.
  • 10.
    Reflection Reflection in C++Next Staticreflection is the ability of a computer program to examine, introspect, and modify its own structure and behavior at compile-time.
  • 11.
    Metaprogramming definition Reflection inC++Next Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves) as their data, or that do part of the work at compile time that would otherwise be done at run-time. (from Wikipedia, some rev.)
  • 12.
    C++ template metaprogramming Reflectionin C++Next auto multiply_by_two(const std::array<int, 3>& array) { auto result = array; for (auto& i: result) i *= 2; return result; } std::array<int, 3> arr1{1, 2, 3}; auto arr2 = multiply_by_two(arr1);
  • 13.
    C++ template metaprogramming Reflectionin C++Next template <class T> struct multiply_by_two; template <class T, T... I> struct multiply_by_two<std::integer_sequence<T, I...>> { using type = std::integer_sequence<T, (I * 2)...>; }; using seq1 = std::integer_sequence<int, 1, 2, 3>; using seq2 = multiply_by_two<seq1>::type;
  • 14.
    C++ constexpr metaprogramming Reflectionin C++Next constexpr auto multiply_by_two(const std::array<int, 3>& array) { auto result = array; for (auto& i: result) i *= 2; return result; } constexpr std::array<int, 3> arr1{1, 2, 3}; constexpr auto arr2 = multiply_by_two(arr1);
  • 15.
  • 16.
  • 17.
    What we actuallyneed… Reflection in C++Next struct foo { int a; double b; string c; }; struct soa_foo { vector<int> as; vector<double> bs; vector<string> cs; };
  • 18.
    Reflection in C++Next classPerson { [[getter, setter]] std::string name; [[getter, setter]] std::string email; }; What we actually need…
  • 19.
    Reflection in C++Next classPerson { [[getter, setter, serialized]] std::string name; [[getter, setter, serialized]] std::string email; }; What we actually need…
  • 20.
    Reflection in C++Next class[[polymorphically_serialized]] Person: IPerson { Person() { /* initializing code here */ } [[getter, setter, serialized]] std::string name; [[getter, setter, serialized]] std::string email; }; What we actually need…
  • 21.
    Study Group 7:Reflection Reflection in C++Next • N4428: Type property queries - 4th revision - date: 2015-04-08 • P0255R0: Reflection via template pack expansion - 5th revision - date: 2016-02-12 • P0194R3: Static reflection - 7th revision - date: 2017-02-06 • P0590R0: A design for static reflection - 1st revision - date: 2017-02-05
  • 22.
    Study Group 7:Reflection Reflection in C++Next • N4428: Type property queries - 4th revision - date: 2015-04-08 • P0255R0: Reflection via template pack expansion - 5th revision - date: 2016-02-12 • P0194R3: Static reflection - 7th revision - date: 2017-02-06 • P0590R0: A design for static reflection - 1st revision - date: 2017-02-05
  • 23.
    Static reflection (P0194R3) Reflectionin C++Next by Matúš Chochlík, Axel Naumann, David Sankel
  • 24.
    P0194R3: Static reflection Reflectionin C++Next • core-language changes: - operator $reflect(x); - where x is an id-expression; - returns a unique generated type for an entity x; - this type satisfies one or more concepts defined in the library; - you operate on these types (metaobjects) by calling meta- operations. • library changes: - std::reflect::Concept<m> - std::reflect::Operation<m>
  • 25.
    P0194R3: Static reflection. Simpleexample Reflection in C++Next std::string person = "John"; using person_m = $reflect(person); static_assert(std::reflect::Variable<person_m>()); std::cout << std::reflect::get_base_name_v<person_m>;
  • 26.
    P0194R3: Static reflection. Simpleexample Reflection in C++Next std::string person = "John"; using person_m = $reflect(person); static_assert(std::reflect::Variable<person_m>()); std::cout << std::reflect::get_base_name_v<person_m>; using type_m = std::reflect::get_type_t<person_m>; static_assert(std::reflect::Type<type_m>());
  • 27.
    P0194R3: Static reflection. Simpleexample Reflection in C++Next std::string person = "John"; using person_m = $reflect(person); static_assert(std::reflect::Variable<person_m>()); std::cout << std::reflect::get_base_name_v<person_m>; using type_m = std::reflect::get_type_t<person_m>; static_assert(std::reflect::Type<type_m>()); using real_type = std::reflect::get_reflected_type_t<type_m>; static_assert(std::is_same_v<real_type, std::string>);
  • 28.
    P0194R3: Static reflection. Meta-objectconcepts Reflection in C++Next namespace std::experimental::reflect { template <class T> concept bool Object(); template <class T> concept bool ObjectSequence(); template <Object T> concept bool Named(); template <Object T> concept bool Alias(); template <Object T> concept bool RecordMember(); template <Object T> concept bool Enumerator(); template <Object T> concept bool Variable(); template <Object T> concept bool ScopeMember(); template <Object T> concept bool Typed(); template <Object T> concept bool Namespace(); template <Object T> concept bool GlobalScope(); template <Object T> concept bool Class(); template <Object T> concept bool Enum(); template <Object T> concept bool Record(); template <Object T> concept bool Scope(); template <Object T> concept bool Type(); template <Object T> concept bool Constant(); template <Object T> concept bool Base(); }
  • 29.
    P0194R3: Static reflection. Class-likethings Reflection in C++Next template <Object T> concept bool Record(); - a union or a class template <Object T> concept bool Class(); - a class or a struct template <Object T> concept bool Base(); - base classes template <Object T> concept bool RecordMember(); - data member and member types
  • 30.
    P0194R3: Static reflection. Scopes Reflectionin C++Next template <Object T> concept bool Namespace(); - a namespace template <Object T> concept bool Scope(); - a namespace, class or enumeration scope template <Object T> concept bool ScopeMember(); - something in a scope template <Object T> concept bool GlobalScope(); - the global namespace, $reflect(::)
  • 31.
    P0194R3: Static reflection. Enums Reflectionin C++Next template <Object T> concept bool Enum(); - an enum template <Object T> concept bool Enumerator(); - an enumerator
  • 32.
    P0194R3: Static reflection. Types Reflectionin C++Next template <Object T> concept bool Typed(); - something that has a type, e.g. member-variable template <Object T> concept bool Type(); - a type
  • 33.
    P0194R3: Static reflection. Expressions Reflectionin C++Next template <Object T> concept bool Variable(); - a variable template <Object T> concept bool Constant(); - a constant-expression, like an enumerator
  • 34.
    P0194R3: Static reflection. Other Reflectionin C++Next template <Object T> concept bool Named(); - something with a name; template <Object T> concept bool Alias(); - an alias, like a typedef template <Object T> concept bool ObjectSequence(); - object-sequence, type-list…
  • 35.
  • 36.
    P0194R3: Static reflection. Enum-to-string Reflectionin C++Next template <class Enum> std::string to_string(Enum e) { using namespace std::reflect; using e_m = $reflect(Enum); static_assert(std::reflect::Enum<e_m>()); std::string result; for_each<get_enumerators_t<e_m>>([&](auto m) { using en_m = decltype(m); if (get_constant_v<en_m> == e) result = get_base_name_v<en_m>; }); return result; }
  • 37.
    P0194R3: Static reflection. Genericequal Reflection in C++Next template <class T> bool generic_equal(const T& a, const T& b) { using namespace std::reflect; using T_m = $reflect(T); static_assert(std::reflect::Class<e_m>()); bool result = true; for_each<get_data_members_t<T_m>>([&](auto m) { using m_t = decltype(m); result &= a.*get_pointer_v<m_t> == b.*get_pointer_v<m_t>; }); return result; }
  • 38.
    P0194R3: Static reflection. Genericequal with unreflect Reflection in C++Next template <class T> bool generic_equal(const T& a, const T& b) { using namespace std::reflect; using T_m = $reflect(T); static_assert(std::reflect::Class<e_m>()); bool result = true; for_each<get_data_members_t<T_m>>([&](auto m) { result &= a.$unreflect(m) == b.$unreflect(m); }); return result; }
  • 39.
    P0194R3: Static reflection. Templatesparametrized by namespace Reflection in C++Next namespace foo { void func1(const std::string&); void func2(int); int func3(int); } namespace bar { void func1(const std::string&); void func2(int); int func3(int); }
  • 40.
    P0194R3: Static reflection. Templatesparametrized by namespace Reflection in C++Next template <class MN> void algorithm(const string& str, int i) { // [foo|bar]::func1(str) $unreflect(MN)::func1(str); // [foo|bar]::func2([foo|bar]::func3(i)) $unreflect(MN)::func2($unreflect(MN)::func3(i)); } void func(const string& str, int i, bool want_foo) { if (want_foo) algorithm<$reflect(foo)>(str, i); else algorithm<$reflect(bar)>(str, i); }
  • 41.
    P0194R3: Static reflection. Stringto identifier transformation Reflection in C++Next struct foo { int bar; }; constexpr const char* bar_name = get_base_name_v<$reflect(foo::bar)>; int get_???bar_name???(const foo&);
  • 42.
    P0194R3: Static reflection. Stringto identifier transformation Reflection in C++Next struct foo { int bar; }; constexpr const char* bar_name = get_base_name_v<$reflect(foo::bar)>; int $identifier(ct_concat(“get_”, bar_name))(const foo&);
  • 43.
    P0194R3: Static reflection. Stringto identifier transformation Reflection in C++Next struct foo { int a; double b; string c; }; struct soa_foo { vector<int> as; vector<double> bs; vector<string> cs; };
  • 44.
    P0194R3: Static reflection Reflectionin C++Next • supported: - variables; - data members; - member types; - enumerators; - template instantiations; - aliases
  • 45.
    P0194R3: Static reflection Reflectionin C++Next • not supported: - declarations in namespaces (except for types); - functions (yet); - class templates (yet)
  • 46.
    P0194R3: Static reflection. Prosand cons Reflection in C++Next • Pros: - reflection of different entities is supported; - very lazy instantiation, only queried data is instantiated; - “you don’t pay for what you don’t use” at compile-time; - a good base for building higher-level and domain-specific libraries; - very extensible
  • 47.
    P0194R3: Static reflection. Prosand cons Reflection in C++Next • Cons: - awkward and verbose usage; - no attribute ideas
  • 48.
    A design forstatic reflection (P0590R0) Reflection in C++Next by Andrew Sutton, Herb Sutter
  • 49.
    P0590R0: A designfor static reflection Reflection in C++Next • core-language changes: - operator $x; - where x is an id-expression; - returns a unique object of a generated type for an entity x; - the object represents its meta information; - you operate on these objects by calling member-functions • library changes: - std::meta::reflection_type<X>
  • 50.
    P0590R0: A designfor static reflection. Simple example Reflection in C++Next std::string person = "John"; auto person_m = $person; static_assert(std::meta::is_variable_v< decltype(person_m)>); std::cout << person_m.name();
  • 51.
    P0590R0: A designfor static reflection. Simple example Reflection in C++Next std::string person = "John"; auto person_m = $person; static_assert(std::meta::is_variable_v< decltype(person_m)>); std::cout << person_m.name(); auto type_m = person_m.type(); static_assert(std::meta::is_type_v<decltype(type_m)>);
  • 52.
    P0590R0: A designfor static reflection. Simple example Reflection in C++Next std::string person = "John"; auto person_m = $person; static_assert(std::meta::is_variable_v< decltype(person_m)>); std::cout << person_m.name(); auto type_m = person_m.type(); static_assert(std::meta::is_type_v<decltype(type_m)>); using real_type = ???;
  • 53.
    P0194R3 vs P0590R0 Enum-to-string Reflectionin C++Next template <class Enum> std::string to_string(Enum e) { using namespace std::reflect; using e_m = $reflect(Enum); static_assert(std::reflect::Enum<e_m>()); std::string result; for_each<get_enumerators_t<e_m>>([&](auto m) { using en_m = decltype(m); if (get_constant_v<en_m> == e) result = get_base_name_v<en_m>; }); return result; }
  • 54.
    P0194R3 vs P0590R0 Enum-to-string Reflectionin C++Next template <class Enum> std::string to_string(Enum e) { using namespace std::meta; auto e_m = $Enum; static_assert(std::meta::is_enum_v<decltype(e_m)>); std::string result; for_each(e_m.enumerators(), [&](auto m) { if (m.value() == e) result = m.name(); }); return result; }
  • 55.
    P0194R3 vs P0590R0 Enum-to-string Reflectionin C++Next template <class Enum> std::string to_string(Enum e) { using namespace std::meta; auto e_m = $Enum; static_assert(std::meta::is_enum_v<decltype(e_m)>); std::string result; for (auto e: e_m.enumerators()) if (m.value() == e) result = m.name(); return result; }
  • 56.
    P0194R3 vs P0590R0 Genericequal Reflection in C++Next template <class T> bool generic_equal(const T& a, const T& b) { bool result = true; for (auto member: $T.member_variables()) { auto ptr = member.pointer(); result &= a.*ptr == b.*ptr; } return result; }
  • 57.
    P0590R0: A designfor static reflection. Pros and cons Reflection in C++Next • Pros: - reflection of different entities is supported; - better syntax; - a good base for building higher-level and domain-specific libraries; - extensible
  • 58.
    P0590R0: A designfor static reflection. Pros and cons Reflection in C++Next • Cons: - some extra data may still be instantiated by compiler; - no attribute ideas
  • 59.
    Thank you foryour attention! Reflection in C++Next