Upload
sergey-platonov
View
1.629
Download
0
Embed Size (px)
Citation preview
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
constexprauto 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);
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
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: 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
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