SlideShare a Scribd company logo
1 of 57
Метаклассы:
воплощаем мечты в реальность
Сергей Садовников
+
+ +
+
+
+
+
Обо мне
Сергей Садовников
Архитектор ПО в компании “Лаборатория
Касперского”
corehard.by
01
CoreHard. Метаклассы: воплощаем мечты в реальность
Метаклассы - что это?
CoreHard. Метаклассы: воплощаем мечты в реальность
02
https://www.youtube.com/watch?v=6nsyX37nsRs
Метаклассы - что это?
CoreHard. Метаклассы: воплощаем мечты в реальность
03
https://www.youtube.com/watch?v=6nsyX37nsRs
Метаклассы - что это?
● Новая языковая сущность
● Управляет генерацией AST и кода
● “Метапрограммирование” в императивном стиле
● Потенциальная замена макросам и некоторым шаблонам
CoreHard. Метаклассы: воплощаем мечты в реальность
04
Метаклассы - зачем?
CoreHard. Метаклассы: воплощаем мечты в реальность
05
https://www.youtube.com/watch?v=80BZxujhY38
Метаклассы - зачем?
Основное назначение:
1. Ещё одна степень обобщения: описывать общие свойства целых групп классов
(“interface”, “value”, “property” и т. д.), создавать библиотеки метаклассов
2. “Концепты на стероидах”: позволяют верифицировать свойства классов в
императивном стиле
3. Inplace-расширение компилятора (и языка): непосредственная манипуляция AST
на этапе компиляции с целью привести объявление класса к нужному виду
(задание новых свойств, добавление методов, перегрузка операторов и т. п.
CoreHard. Метаклассы: воплощаем мечты в реальность
06
Базируются на:
1. Static reflection (p0712)
2. Generative metaprogramming: code generation and injection (p0712, Code generation in
C++)
Описано в p0707 (revision 3)
Метаклассы - пример
struct IEnumerator : public IUnknown
{
virtual ~IEnumerator() {}
virtual HRESULT Reset() = 0;
virtual HRESULT MoveNext(BOOL* succeeded) = 0;
virtual HRESULT Current(IUnknown** item) = 0;
};
CoreHard. Метаклассы: воплощаем мечты в реальность
07
Метаклассы - пример
interface IEnumerator
{
void Reset();
BOOL MoveNext();
IUnknown* Current();
};
CoreHard. Метаклассы: воплощаем мечты в реальность
08
Метаклассы - пример
interface IEnumerator
{
void Reset();
BOOL MoveNext();
IUnknown* Current();
};
CoreHard. Метаклассы: воплощаем мечты в реальность
09
Метакласс
Метаклассы - пример
$class interface {
virtual ~interface() {}
constexpr {
compiler.require($interface.variables().empty(), "interfaces may not contain data");
for (auto f : $interface.functions()) {
compiler.require(!f.is_copy() && !f.is_move(),
"interfaces may not copy or move; consider a virtual clone() instead");
if (!f.has_access())
f.make_public();
compiler.require(f.is_public(), "interface functions must be public");
f.make_pure_virtual();
f.parameters().add($f.return_type() *);
f.set_type(HRESULT);
f.bases().push_front(IUnknown);
}
}
};
CoreHard. Метаклассы: воплощаем мечты в реальность
10
Метаклассы - пример
$class interface {
virtual ~interface() {}
constexpr {
compiler.require($interface.variables().empty(), "interfaces may not contain data");
for (auto f : $interface.functions()) {
compiler.require(!f.is_copy() && !f.is_move(),
"interfaces may not copy or move; consider a virtual clone()
instead");
if (!f.has_access())
f.make_public();
compiler.require(f.is_public(), "interface functions must be public");
f.make_pure_virtual();
f.parameters().add($f.return_type() *);
f.set_type(HRESULT);
f.bases().push_front(IUnknown);
}
}
};
CoreHard. Метаклассы: воплощаем мечты в реальность
11
interface IEnumerator
{
void Reset();
BOOL MoveNext();
IUnknown* Current();
};
struct IEnumerator : public IUnknown
{
virtual ~IEnumerator() {}
virtual HRESULT Reset() = 0;
virtual HRESULT MoveNext(BOOL* succeeded) = 0;
virtual HRESULT Current(IUnknown** item) = 0;
};
Метаклассы - пример
$class interface {
virtual ~interface() {}
constexpr {
compiler.require($interface.variables().empty(), "interfaces may not contain data");
for (auto f : $interface.functions()) {
compiler.require(!f.is_copy() && !f.is_move(),
"interfaces may not copy or move; consider a virtual clone() instead");
if (!f.has_access())
f.make_public();
compiler.require(f.is_public(), "interface functions must be public");
f.make_pure_virtual();
f.parameters().add($f.return_type() *);
f.set_type(HRESULT);
f.bases().push_front(IUnknown);
}
}
};
CoreHard. Метаклассы: воплощаем мечты в реальность
12
В соответствии с p0707r1/p0707r2
Метаклассы - пример
template<typename T, typename S>
constexpr void interface(T target, const S source) {
compiler.require(source.variables().empty(), "interfaces may not contain data");
for (auto f : source.member_functions()) {
compiler.require(!f.is_copy() && !f.is_move(), "interfaces may not copy or move; consider a virtual clone() instead");
if (!f.has_access())
f.make_public();
compiler.require(f.is_public(), "interface functions must be public");
auto ret = f.return_type();
if (ret == $void) {
-> (target) class {
virtual HRESULT idexpr(f)(__inject(f.parameters())) = 0;
};
} else {
-> (target) class {
virtual HRESULT idexpr(f)(__inject(f.parameters()), typename(ret)* retval) = 0;
};
}
}
}
CoreHard. Метаклассы: воплощаем мечты в реальность
13
В соответствии с p0707r3
Метаклассы - пример
constexpr void basic_enum(meta::type target, const meta::type source) {
value(target, source); // a basic_enum is-a value
compiler.require(source.variables().size() > 0, "an enum cannot be empty");
if (src.variables().front().type().is_auto())
->(target) { using U = int; } // underlying type
else ->(target) { using U = (src.variables().front().type())$; }
for (auto o : source.variables()) {
if (!o.has_access()) o.make_public();
if (!o.has_storage()) o.make_constexpr();
if (o.has_auto_type()) o.set_type(U);
compiler.require(o.is_public(), "enumerators must be public");
compiler.require(o.is_constexpr(), "enumerators must be constexpr");
compiler.require(o.type() == U, "enumerators must use same type");
->(target) o;
}
->(target) { U value; } // the instance value
compiler.require(source.functions().empty(), "enumerations must not have functions");
compiler.require(source.bases().empty(), "enumerations must not have base classes");
}
CoreHard. Метаклассы: воплощаем мечты в реальность
14
Метаклассы
Проблемы:
● Базируется на ещё не принятых пропозалах -> предлагаемый синтаксис может
меняться
● Неизвестно, когда всё это примут. По некоторым оценкам - не раньше C++2z
● Не все возможные варианты использования детально рассмотрены в публично
доступных документах
CoreHard. Метаклассы: воплощаем мечты в реальность
15
Метаклассы
Проблемы:
● Базируется на ещё не принятых пропозалах -> предлагаемый синтаксис может
меняться
● Неизвестно, когда всё это примут. По некоторым оценкам - не раньше C++2z
● Не все возможные варианты использования детально рассмотрены в публично
доступных документах
CoreHard. Метаклассы: воплощаем мечты в реальность
16
А если хочется раньше?
● Ждать принятия в стандарт и поддержки компиляторами
● Использовать шаблонную магию и макросы
● Реализовать и использовать сторонние утилиты
Метаклассы
Проблемы:
● Базируется на ещё не принятых пропозалах -> предлагаемый синтаксис может
меняться
● Неизвестно, когда всё это примут. По некоторым оценкам - не раньше C++2z
● Не все возможные варианты использования детально рассмотрены в публично
доступных документах
CoreHard. Метаклассы: воплощаем мечты в реальность
17
А если хочется раньше?
● Ждать принятия в стандарт и поддержки компиляторами
● Использовать шаблонную магию и макросы
● Реализовать и использовать сторонние утилиты
Метаклассы - сторонняя утилита
Достоинства:
● Не требуется особой поддержки со стороны компиляторов
● Реализация в рамках актуальных стандартов
● Может быть легко встроена в сборочный тулчейн
● Может сделать кодовую базу проектов проще и упростить поддержку
CoreHard. Метаклассы: воплощаем мечты в реальность
18
Метаклассы - сторонняя утилита
Достоинства:
● Не требуется особой поддержки со стороны компиляторов
● Реализация в рамках актуальных стандартов
● Может быть легко встроена в сборочный тулчейн
● Может сделать кодовую базу проектов проще и упростить поддержку
CoreHard. Метаклассы: воплощаем мечты в реальность
19
Недостатки:
● Не соответствует одной из целей создания метаклассов (“Eliminate the need to
invent non-C++ “side languages” and special compilers, such as Qt moc, COM MIDL, and
C++/CX”)
● Собственный “птичий” язык для описания специальных конструкций
● Не всегда удобное использование предлагаемых возможностей
● Потенциальная несовместимость с итоговым вариантом пропозала
Метаклассы - сторонняя утилита
Основные возможности:
● Позволяет объявлять метаклассы
● Позволяет объявлять инстансы конкретных метаклассов
● В метаклассах позволяет проверять свойства инстансов и генерировать
диагностику
● Позволяет внедрять в инстансы метаклассов новый код/изменять существующий
● Всё это в рамках одной кодовой базы
CoreHard. Метаклассы: воплощаем мечты в реальность
20
Требования:
● Совместимость со стандартами C++14/17 (идеально - с C++11)
● Совместимость с популярными компиляторами (gcc/clang/MSVC)
● Лёгкость интеграции в сборочный тулчейн
● Относительная простота использования возможностей
● C++ на входе - C++ на выходе, ничего больше
Метаклассы - сторонняя утилита
Основная идея реализации:
CoreHard. Метаклассы: воплощаем мечты в реальность
21
Metaclass declaration
header
Metaclass instance
header
Metaclasses
processing tool
.h-file with processed
metaclass instance
.cpp-file with processed
metaclass instance
Метаклассы - использование утилиты
$_metaclass(Interface) {
static void GenerateDecl() {
compiler.message("Hello world from metaprogrammer!");
compiler.require($Interface.variables().empty(), "Interface may not contain data members");
$_inject(public) {
enum {InterfaceId = 100500};
}
for (auto& f : $Interface.functions()) {
compiler.require(f.is_implicit() || (!f.is_copy_ctor() && !f.is_move_ctor()),
"Interface can't contain copy or move constructor");
compiler.require(f.is_public(), "Inteface function must be public");
f.make_pure_virtual();
}
}
};
CoreHard. Метаклассы: воплощаем мечты в реальность
22
Метаклассы - использование утилиты
$_metaclass(Interface) {
static void GenerateDecl() {
compiler.message("Hello world from metaprogrammer!");
compiler.require($Interface.variables().empty(), "Interface may not contain data members");
$_inject(public) {
enum {InterfaceId = 100500};
}
for (auto& f : $Interface.functions()) {
compiler.require(f.is_implicit() || (!f.is_copy_ctor() && !f.is_move_ctor()),
"Interface can't contain copy or move constructor");
compiler.require(f.is_public(), "Inteface function must be public");
f.make_pure_virtual();
}
}
};
CoreHard. Метаклассы: воплощаем мечты в реальность
23
Макрос для объявление метакласса
Метод, отвечающий за генерацию декларации
Интерфейс к “компилятору”
Макрос для внедрения нового кода в класс
Ссылка на обрабатываемый инстанс метакласса
Метаклассы - использование утилиты
$_class(TestIface, Interface)
{
void TestMethod1();
std::string TestMethod2(int param)
const;
};
CoreHard. Метаклассы: воплощаем мечты в реальность
24
Метаклассы - использование утилиты
$_class(TestIface, Interface)
{
void TestMethod1();
std::string TestMethod2(int param)
const;
};
CoreHard. Метаклассы: воплощаем мечты в реальность
25
$_metaclass(Interface) {
static void GenerateDecl() {
compiler.message("Hello world from metaprogrammer!");
compiler.require($Interface.variables().empty(), "Interface may not contain data members");
$_inject(public) {
enum {InterfaceId = 100500};
}
for (auto& f : $Interface.functions()) {
compiler.require(f.is_implicit() || (!f.is_copy_ctor() && !f.is_move_ctor()),
"Interface can't contain copy or move constructor");
compiler.require(f.is_public(), "Inteface function must be public");
f.make_pure_virtual();
}
}
};
class TestIface {
public:
enum { InterfaceId = 100500 };
virtual void TestMethod1() = 0;
virtual std::string TestMethod2(int param) const = 0;
protected:
private:
};
Метаклассы - использование утилиты
struct TestStruct
{
int a;
std::string b;
template <typename Arch>
void serialize(Arch &ar, unsigned int ver)
{
ar & a;
ar & b;
}
};
CoreHard. Метаклассы: воплощаем мечты в реальность
26
Метаклассы - использование утилиты
struct TestStruct
{
int a;
std::string b;
template <typename Arch>
void serialize(Arch &ar, unsigned int ver)
{
ar & a;
ar & b;
}
};
CoreHard. Метаклассы: воплощаем мечты в реальность
27
struct AnotherTestStruct1
{
// Members
template <typename Arch>
void serialize(Arch &ar, unsigned int ver)
{
// Serializer impl
}
};
struct AnotherTestStruct2
{
// Members
template <typename Arch>
void serialize(Arch &ar, unsigned int ver)
{
// Serializer impl
}
};
struct AnotherTestStruct3
{
// Members
template <typename Arch>
void serialize(Arch &ar, unsigned int ver)
{
// Serializer impl
}
};
struct AnotherTestStruct4
{
// Members
template <typename Arch>
void serialize(Arch &ar, unsigned int ver)
{
// Serializer impl
}
};
struct AnotherTestStruct5
{
// Members
template <typename Arch>
void serialize(Arch &ar, unsigned int ver)
{
// Serializer impl
}
};
Метаклассы - использование утилиты
$_struct(TestStruct, BoostSerializable)
{
int a;
std::string b;
};
CoreHard. Метаклассы: воплощаем мечты в реальность
28
Метаклассы - использование утилиты
$_metaclass(BoostSerializable) {
static void GenerateDecl() {
$_inject(public) [&, name="serialize"](auto& ar, const unsigned int ver) -> void
{
$_constexpr for (auto& v : $BoostSerializable.variables())
$_inject(_) ar & $_v(v.name());
};
}
};
CoreHard. Метаклассы: воплощаем мечты в реальность
29
Метаклассы - использование утилиты
$_struct(TestStruct, BoostSerializable)
{
int a;
std::string b;
};
CoreHard. Метаклассы: воплощаем мечты в реальность
30
$_metaclass(BoostSerializable) {
static void GenerateDecl() {
$_inject(public) [&, name="serialize"](auto& ar, const unsigned int ver) -> void
{
$_constexpr for (auto& v : $BoostSerializable.variables())
$_inject(_) ar & $_v(v.name());
};
}
};
class TestStruct {
public:
template <typename T0> void serialize(T0 &ar, const unsigned int ver) {
ar & a;
ar & b;
}
int a;
std::string b;
};
Метаклассы - использование утилиты
$_metaclass(BoostSerializableSplitted) {
static void GenerateDecl() {
$_inject(public) [&, name="load"](auto& ar, unsigned int ver) -> void
{
$_constexpr for (auto& v : $BoostSerializableSplitted.variables())
$_inject(_) ar >> $_v(v.name());
};
$_inject(public) [&, name="save", is_const=true](auto& ar, unsigned int ver) -> void
{
$_constexpr for (auto& v : $BoostSerializableSplitted.variables())
$_inject(_) ar << $_v(v.name());
};
$_inject(public) [&, name="serialize"](auto& ar, const unsigned int ver) -> void
{
boost::serialization::split_member(ar, $_safe(*this), ver);
};
}
};
CoreHard. Метаклассы: воплощаем мечты в реальность
31
Метаклассы - использование утилиты
class TestStruct {
public:
template <typename T0> void load(T0 &ar, unsigned int ver) {
ar << a;
ar << b;
}
template <typename T0> void save(T0 &ar, unsigned int ver) const {
ar >> a;
ar >> b;
}
template <typename T0> void serialize(T0 &ar, const unsigned int ver) {
boost::serialization::split_member(ar, *this, ver);
}
int a;
std::string b;
protected:
private:
};
CoreHard. Метаклассы: воплощаем мечты в реальность
32
Метаклассы - использование утилиты
$_metaclass(Name) - макрос, с помощью которого объявляется метакласс
$_class(Name, MetaclassName) - макрос, с помощью которого объявляется инстанс
метакласса
$_inject(Visibility) - макрос-префикс, который приводит к вставке следующего за ним
блока в тело инстанса метакласса
$_constexpr() - макрос-префикс, помечающий следующий за ним оператор как
вычисляемый на этапе компиляции
$_inject_xxx(Name, Visibility), где XXX - это enum, struct, class или union - макрос-префикс,
который приводит к вставке следующего за ним блока в тело инстанса метакласса в
виде отдельной структуры, enum’а, класса или объединения
$_n(expr) - макрос, который заменяется значением выражения expr, вычисленного на
этапе компиляции
$_t(expr) - макрос, который заменяется типом выражения expr, вычисленного на этапе
компиляции
$_safe(expr) - макрос, который заменяется на expr
CoreHard. Метаклассы: воплощаем мечты в реальность
33
Метаклассы - использование утилиты
compiler - экземпляр класса meta::CompilerImpl, предоставляющий доступ к глобальным
методам типа require, error, message и т. п.
meta::TypeInfo - класс, предоставляющий различную информацию о конкретном типе
meta::MemberInfo - класс, предоставляющий различную информацию о конкретном
члене класса
meta::MethodInfo - класс, предоставляющий различную информацию о конкретном
методе класса
meta::ClassInfo - класс, предоставляющий различную информацию о конкретном
классе. Видимые в методах реализации метакласса переменные вида $Interface -
именно этого типа
CoreHard. Метаклассы: воплощаем мечты в реальность
34
Метаклассы - использование утилиты
Перечисленные типы (и переменные), по сути - read/write-интерфейс к AST и
компилятору
CoreHard. Метаклассы: воплощаем мечты в реальность
35
Metaclasses processing tool
Metaclasses processing tool
CoreHard. Метаклассы: воплощаем мечты в реальность
36
Metaclass
declaration
Metaclass
instance
clang frontend
AST
header file
source file
diagnostic
output
metaclasses
processor
Sources
Messages
Metaclasses processing tool
CoreHard. Метаклассы: воплощаем мечты в реальность
37
C++
interpreter
Source code
clang
frontend/AST
matcher
.h file
.cpp file
diagnostic
output
AST reflector
Source code
generator
Интерпретатор C++
1. Детально анализирует AST декларации метакласса
2. Фактически исполняет код декларации метакласса используя в качестве
исходных данных отрефлексированный AST конкретного инстанса
3. Обеспечивает печать диагностических сообщений и проверку предикатов
4. Модифицирует отрефлексированный AST в соответствии с прописанной в
меткалассе логикой
5. Инжектирует в инстанс метакласса заданные фрагменты кода с учётом constexpr-
конструкций
CoreHard. Метаклассы: воплощаем мечты в реальность
38
Интерпретатор C++
CoreHard. Метаклассы: воплощаем мечты в реальность
39
Анализатор и интерпретатор операторов
Вычислитель выражений
Интерфейс к внутренней инфраструктуре
Интерпретатор C++
compiler.require($Interface.variables().empty(), "Interface may not contain data members");
CoreHard. Метаклассы: воплощаем мечты в реальность
39
Интерпретатор C++
compiler.require($Interface.variables().empty(), "Interface may not contain data members");
CoreHard. Метаклассы: воплощаем мечты в реальность
40
1. Интерпретатор операторов определяет, что это выражение
Интерпретатор C++
compiler.require($Interface.variables().empty(), "Interface may not contain data members");
CoreHard. Метаклассы: воплощаем мечты в реальность
41
1. Интерпретатор операторов определяет, что это выражение
2. Вычислитель определяет, что выражение - это вызов члена класса
Интерпретатор C++
compiler.require($Interface.variables().empty(), "Interface may not contain data members");
CoreHard. Метаклассы: воплощаем мечты в реальность
42
1. Интерпретатор операторов определяет, что это выражение
2. Вычислитель определяет, что выражение - это вызов члена класса
3. Объект, к которому применяется вызов метода, отображается на реализацию
интерфейса к компилятору
Интерпретатор C++
compiler.require($Interface.variables().empty(), "Interface may not contain data members");
CoreHard. Метаклассы: воплощаем мечты в реальность
43
1. Интерпретатор операторов определяет, что это выражение
2. Вычислитель определяет, что выражение - это вызов члена класса
3. Объект, к которому применяется вызов метода, отображается на реализацию
интерфейса к компилятору
4. Начинают вычисляться параметры
Интерпретатор C++
compiler.require($Interface.variables().empty(), "Interface may not contain data members");
CoreHard. Метаклассы: воплощаем мечты в реальность
44
1. Интерпретатор операторов определяет, что это выражение
2. Вычислитель определяет, что выражение - это вызов члена класса
3. Объект, к которому применяется вызов метода, отображается на реализацию
интерфейса к компилятору
4. Начинают вычисляться параметры
5. Первый параметр - вызов члена класса
Интерпретатор C++
compiler.require($Interface.variables().empty(), "Interface may not contain data members");
CoreHard. Метаклассы: воплощаем мечты в реальность
45
1. Интерпретатор операторов определяет, что это выражение
2. Вычислитель определяет, что выражение - это вызов члена класса
3. Объект, к которому применяется вызов метода, отображается на реализацию
интерфейса к компилятору
4. Начинают вычисляться параметры
5. Первый параметр - вызов члена класса
6. ‘$Interface’ отображается на дескриптор инстанса метакласса
Интерпретатор C++
compiler.require($Interface.variables().empty(), "Interface may not contain data members");
CoreHard. Метаклассы: воплощаем мечты в реальность
46
1. Интерпретатор операторов определяет, что это выражение
2. Вычислитель определяет, что выражение - это вызов члена класса
3. Объект, к которому применяется вызов метода, отображается на реализацию
интерфейса к компилятору
4. Начинают вычисляться параметры
5. Первый параметр - вызов члена класса
6. ‘$Interface’ отображается на дескриптор инстанса метакласса
7. Последовательно вызываются: метод, возвращающий коллекцию переменных, а
затем - ‘empty()’
Интерпретатор C++
compiler.require($Interface.variables().empty(), "Interface may not contain data members");
CoreHard. Метаклассы: воплощаем мечты в реальность
47
1. Интерпретатор операторов определяет, что это выражение
2. Вычислитель определяет, что выражение - это вызов члена класса
3. Объект, к которому применяется вызов метода, отображается на реализацию
интерфейса к компилятору
4. Начинают вычисляться параметры
5. Первый параметр - вызов члена класса
6. ‘$Interface’ отображается на дескриптор инстанса метакласса
7. Последовательно вызываются: метод, возвращающий коллекцию переменных, а
затем - ‘empty()’
8. Второй параметр, строковый литерал, конвертируется в строку
Интерпретатор C++
compiler.require($Interface.variables().empty(), "Interface may not contain data members");
CoreHard. Метаклассы: воплощаем мечты в реальность
48
1. Интерпретатор операторов определяет, что это выражение
2. Вычислитель определяет, что выражение - это вызов члена класса
3. Объект, к которому применяется вызов метода, отображается на реализацию
интерфейса к компилятору
4. Начинают вычисляться параметры
5. Первый параметр - вызов члена класса
6. ‘$Interface’ отображается на дескриптор инстанса метакласса
7. Последовательно вызываются: метод, возвращающий коллекцию переменных, а
затем - ‘empty()’
8. Второй параметр, строковый литерал, конвертируется в строку
9. Вызывается метод ‘require’, который в зависимости от значения первого
параметра либо выводит диагностическое сообщение, либо нет
Интерпретатор C++
Нюансы реализации:
● ОЧЕНЬ СЛОЖНОЕ И ПОДРОБНОЕ AST
● Необходимость следить за областями видимости и, соответственно, временем
жизни объектов и промежуточных результатов вычислений
● Логика вычисления некоторых конструкций нетривиальна. Например, range-based
for loop
● Необходимость отделять то, что нужно интерпретировать, от того, что нужно
инжектировать в результирующий код
CoreHard. Метаклассы: воплощаем мечты в реальность
49
Интерпретатор C++
● Связка boost::variant + boost::apply_visitor + C++14 + SFINAE - очень мощная.
Позволяет упростить ряд конструкций.
● Атрибуты, введённые в язык, очень сильно помогают в разметке узлов AST и их
последующем анализе
● Нет видимой необходимости поддерживать весь набор базовых типов в C++
CoreHard. Метаклассы: воплощаем мечты в реальность
50
Интеграция с системой сборки
include_directories(
${CODEGEN_DIR}
${CODEGEN_ROOT_DIR}/include
)
set (CODEGEN_DIR ${CMAKE_CURRENT_BINARY_DIR}/codegen)
file (MAKE_DIRECTORY ${CODEGEN_DIR}/generated)
set (METACLASSES_GEN_FILE ${CODEGEN_DIR}/generated/structs.meta.h)
set (CODEGEN_ROOT_DIR "d:/projects/work/Personal/autoprogrammer/autoprogrammer")
set (CODEGEN_TOOL "d:/projects/work/Personal/autoprogrammer/autoprogrammer-build/MSVC2015-Debug/fl-codegen.exe")
add_custom_command(OUTPUT ${METACLASSES_GEN_FILE}
COMMAND ${CODEGEN_TOOL} ARGS -gen-metaclasses -show-clang-diag -ohdr ${METACLASSES_GEN_FILE} -input
${CMAKE_CURRENT_SOURCE_DIR}/structs.h -- clang-cl -std=c++14 -x c++ ${CMAKE_CXX_FLAGS} -I ${CODEGEN_ROOT_DIR}/include -I
${BOOST_ROOT}
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/structs.h
DEPENDS ${CODEGEN_BIN_NAME} serialization_metaclass.h
COMMENT "Generating metaclasses implementation for ${CMAKE_CURRENT_SOURCE_DIR}/structs.h"
)
add_executable(${PROJECT_NAME} "main.cpp" "serialization_metaclass.h" "structs.h" ${METACLASSES_GEN_FILE})
target_link_libraries(${PROJECT_NAME} Boost::serialization)
CoreHard. Метаклассы: воплощаем мечты в реальность
51
Интеграция с системой сборки
include_directories(
${CODEGEN_DIR}
${CODEGEN_ROOT_DIR}/include
)
set (CODEGEN_DIR ${CMAKE_CURRENT_BINARY_DIR}/codegen)
file (MAKE_DIRECTORY ${CODEGEN_DIR}/generated)
set (METACLASSES_GEN_FILE ${CODEGEN_DIR}/generated/structs.meta.h)
set (CODEGEN_ROOT_DIR "d:/projects/work/Personal/autoprogrammer/autoprogrammer")
set (CODEGEN_TOOL "d:/projects/work/Personal/autoprogrammer/autoprogrammer-build/MSVC2015-Debug/fl-codegen.exe")
add_custom_command(OUTPUT ${METACLASSES_GEN_FILE}
COMMAND ${CODEGEN_TOOL} ARGS -gen-metaclasses -ohdr ${METACLASSES_GEN_FILE} -input
${CMAKE_CURRENT_SOURCE_DIR}/structs.h -- clang-cl -std=c++14 -x c++ ${CMAKE_CXX_FLAGS} -I ${CODEGEN_ROOT_DIR}/include -I
${BOOST_ROOT}
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/structs.h
DEPENDS ${CODEGEN_BIN_NAME} serialization_metaclass.h
COMMENT "Generating metaclasses implementation for ${CMAKE_CURRENT_SOURCE_DIR}/structs.h"
)
add_executable(${PROJECT_NAME} "main.cpp" "serialization_metaclass.h" "structs.h" ${METACLASSES_GEN_FILE})
target_link_libraries(${PROJECT_NAME} Boost::serialization)
CoreHard. Метаклассы: воплощаем мечты в реальность
52
Дальнейшие планы
● Доработка основных возможностей интерпретатора
● Отладка и настройка сборки под разные системы и компиляторы
● Докер-образы с уже установленной утилитой
● Расширение возможностей frontend’а:
○ манипуляция с типами
○ возможность генерации не только в .h-файлы, но и в .cpp
○ возможность задания нескольких метаклассов для одного инстанса
○ приведение в соответствие с последней (r4) ревизии p0707
CoreHard. Метаклассы: воплощаем мечты в реальность
53
Полезные ссылки
● Пропозал по метаклассам: http://www.open-
std.org/jtc1/sc22/wg21/docs/papers/2018/p0707r3.pdf
● Пропозал по static reflection (один из):http://www.open-
std.org/jtc1/sc22/wg21/docs/papers/2017/p0712r0.pdf
● Доклад Герба Саттера с ACCU 2017: https://www.youtube.com/watch?v=6nsyX37nsRs
● Доклад Герба Саттера с CppCon 2018: https://www.youtube.com/watch?v=80BZxujhY38
● Реализация metaclasses processing tool:
https://github.com/flexferrum/autoprogrammer/tree/metaclasses
● Презентация по “автопрограммисту”:
https://docs.google.com/presentation/d/1v0lJqkQVrDUbaKy7_79Vg67EcrNKpBB9yruZIvo8f0c/e
dit?usp=sharing
CoreHard. Метаклассы: воплощаем мечты в реальность
54
+
+ +
+
+
+
+
Спасибо!
Вопросы? :)
Сергей Садовников flexferrum@gmail.com
+

More Related Content

What's hot

Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013ScalaNsk
 
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to UsZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to UsZFConf Conference
 
Scala: что, как и зачем?
Scala: что, как и зачем?Scala: что, как и зачем?
Scala: что, как и зачем?Roman Timushev
 
C++ осень 2012 лекция 9
C++ осень 2012 лекция 9C++ осень 2012 лекция 9
C++ осень 2012 лекция 9Technopark
 
Михаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знанияМихаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знанияYandex
 
JavaScript Базовый. Занятие 03.
JavaScript Базовый. Занятие 03.JavaScript Базовый. Занятие 03.
JavaScript Базовый. Занятие 03.Igor Shkulipa
 
Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Sergey Platonov
 
Инструментируй это
Инструментируй этоИнструментируй это
Инструментируй этоRoman Dvornov
 
Поговорим о JavaScript, основы и современные тенденции развития языка
Поговорим о JavaScript, основы и современные тенденции развития языкаПоговорим о JavaScript, основы и современные тенденции развития языка
Поговорим о JavaScript, основы и современные тенденции развития языкаAlexander Kucherenko
 
C++ осень 2013 лекция 3
C++ осень 2013 лекция 3C++ осень 2013 лекция 3
C++ осень 2013 лекция 3Technopark
 
C++ осень 2013 лекция 7
C++ осень 2013 лекция 7C++ осень 2013 лекция 7
C++ осень 2013 лекция 7Technopark
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаSergey Platonov
 
"Инструментарий разработчика iOS: Xcode, AppCode и сторонние инструменты". Ма...
"Инструментарий разработчика iOS: Xcode, AppCode и сторонние инструменты". Ма..."Инструментарий разработчика iOS: Xcode, AppCode и сторонние инструменты". Ма...
"Инструментарий разработчика iOS: Xcode, AppCode и сторонние инструменты". Ма...Yandex
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Sergey Platonov
 
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
Объектно-Ориентированное Программирование на C++, Лекции  3 и 4 Объектно-Ориентированное Программирование на C++, Лекции  3 и 4
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4 Dima Dzuba
 
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Dima Dzuba
 
Alexander Dymo - IT Jam 2009 - Ruby: Beaty Or The Beast
Alexander Dymo - IT Jam 2009 - Ruby: Beaty Or The BeastAlexander Dymo - IT Jam 2009 - Ruby: Beaty Or The Beast
Alexander Dymo - IT Jam 2009 - Ruby: Beaty Or The BeastAlexander Dymo
 
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)Ontico
 

What's hot (20)

Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013
 
Scala для всех (РИФ 2015)
Scala для всех (РИФ 2015)Scala для всех (РИФ 2015)
Scala для всех (РИФ 2015)
 
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to UsZFConf 2010: What News Zend Framework 2.0 Brings to Us
ZFConf 2010: What News Zend Framework 2.0 Brings to Us
 
Scala: что, как и зачем?
Scala: что, как и зачем?Scala: что, как и зачем?
Scala: что, как и зачем?
 
C++ осень 2012 лекция 9
C++ осень 2012 лекция 9C++ осень 2012 лекция 9
C++ осень 2012 лекция 9
 
Михаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знанияМихаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знания
 
Component Inspector
Component InspectorComponent Inspector
Component Inspector
 
JavaScript Базовый. Занятие 03.
JavaScript Базовый. Занятие 03.JavaScript Базовый. Занятие 03.
JavaScript Базовый. Занятие 03.
 
Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++
 
Инструментируй это
Инструментируй этоИнструментируй это
Инструментируй это
 
Поговорим о JavaScript, основы и современные тенденции развития языка
Поговорим о JavaScript, основы и современные тенденции развития языкаПоговорим о JavaScript, основы и современные тенденции развития языка
Поговорим о JavaScript, основы и современные тенденции развития языка
 
C++ осень 2013 лекция 3
C++ осень 2013 лекция 3C++ осень 2013 лекция 3
C++ осень 2013 лекция 3
 
C++ осень 2013 лекция 7
C++ осень 2013 лекция 7C++ осень 2013 лекция 7
C++ осень 2013 лекция 7
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладка
 
"Инструментарий разработчика iOS: Xcode, AppCode и сторонние инструменты". Ма...
"Инструментарий разработчика iOS: Xcode, AppCode и сторонние инструменты". Ма..."Инструментарий разработчика iOS: Xcode, AppCode и сторонние инструменты". Ма...
"Инструментарий разработчика iOS: Xcode, AppCode и сторонние инструменты". Ма...
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++
 
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
Объектно-Ориентированное Программирование на C++, Лекции  3 и 4 Объектно-Ориентированное Программирование на C++, Лекции  3 и 4
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
 
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
 
Alexander Dymo - IT Jam 2009 - Ruby: Beaty Or The Beast
Alexander Dymo - IT Jam 2009 - Ruby: Beaty Or The BeastAlexander Dymo - IT Jam 2009 - Ruby: Beaty Or The Beast
Alexander Dymo - IT Jam 2009 - Ruby: Beaty Or The Beast
 
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
 

Similar to C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей Садовников

C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.Igor Shkulipa
 
Поддержка Java 8 в Excelsior JET
Поддержка Java 8 в Excelsior JET Поддержка Java 8 в Excelsior JET
Поддержка Java 8 в Excelsior JET Nikita Lipsky
 
C# Desktop. Занятие 12.
C# Desktop. Занятие 12.C# Desktop. Занятие 12.
C# Desktop. Занятие 12.Igor Shkulipa
 
Ecma script 6 in action
Ecma script 6 in actionEcma script 6 in action
Ecma script 6 in actionYuri Trukhin
 
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий solit
 
Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?Vasil Remeniuk
 
Java 8 Support at the JVM Level
Java 8 Support at the JVM LevelJava 8 Support at the JVM Level
Java 8 Support at the JVM LevelNikita Lipsky
 
Теория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямТеория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямSergey Staroletov
 
Как выглядит современный фронтенд
Как выглядит современный фронтендКак выглядит современный фронтенд
Как выглядит современный фронтендTimophy Chaptykov
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioAndrey Karpov
 
C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.Igor Shkulipa
 
Cтиль программирования
Cтиль программированияCтиль программирования
Cтиль программированияConstantin Kichinsky
 
Корпоративное приложение на Rails
Корпоративное приложение на RailsКорпоративное приложение на Rails
Корпоративное приложение на RailsAndrei Kaleshka
 
JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"oelifantiev
 
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полнойОмские ИТ-субботники
 
Как мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальКак мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальBadoo Development
 
Lift, play, akka, rails part1
Lift, play, akka, rails part1Lift, play, akka, rails part1
Lift, play, akka, rails part1Eduard Antsupov
 
Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!Vladimir Kochetkov
 
Roslyn API : SyntaxTree vs CodeDom, SemanticModel vs Reflection
Roslyn API: SyntaxTree vs CodeDom, SemanticModel vs ReflectionRoslyn API: SyntaxTree vs CodeDom, SemanticModel vs Reflection
Roslyn API : SyntaxTree vs CodeDom, SemanticModel vs ReflectionDenis Tsvettsih
 

Similar to C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей Садовников (20)

C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.
 
Поддержка Java 8 в Excelsior JET
Поддержка Java 8 в Excelsior JET Поддержка Java 8 в Excelsior JET
Поддержка Java 8 в Excelsior JET
 
C# Desktop. Занятие 12.
C# Desktop. Занятие 12.C# Desktop. Занятие 12.
C# Desktop. Занятие 12.
 
Ecma script 6 in action
Ecma script 6 in actionEcma script 6 in action
Ecma script 6 in action
 
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
 
Zend Framework и Doctrine
Zend Framework и DoctrineZend Framework и Doctrine
Zend Framework и Doctrine
 
Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?
 
Java 8 Support at the JVM Level
Java 8 Support at the JVM LevelJava 8 Support at the JVM Level
Java 8 Support at the JVM Level
 
Теория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямТеория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциям
 
Как выглядит современный фронтенд
Как выглядит современный фронтендКак выглядит современный фронтенд
Как выглядит современный фронтенд
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
 
C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.
 
Cтиль программирования
Cтиль программированияCтиль программирования
Cтиль программирования
 
Корпоративное приложение на Rails
Корпоративное приложение на RailsКорпоративное приложение на Rails
Корпоративное приложение на Rails
 
JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"
 
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
 
Как мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальКак мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон Довгаль
 
Lift, play, akka, rails part1
Lift, play, akka, rails part1Lift, play, akka, rails part1
Lift, play, akka, rails part1
 
Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!
 
Roslyn API : SyntaxTree vs CodeDom, SemanticModel vs Reflection
Roslyn API: SyntaxTree vs CodeDom, SemanticModel vs ReflectionRoslyn API: SyntaxTree vs CodeDom, SemanticModel vs Reflection
Roslyn API : SyntaxTree vs CodeDom, SemanticModel vs Reflection
 

More from corehard_by

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...corehard_by
 
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...corehard_by
 
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений ОхотниковC++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотниковcorehard_by
 
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титовcorehard_by
 
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...corehard_by
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишковcorehard_by
 
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...corehard_by
 
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...corehard_by
 
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...corehard_by
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...corehard_by
 
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...corehard_by
 
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел ФилоновC++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филоновcorehard_by
 
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan ČukićC++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukićcorehard_by
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakovacorehard_by
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухинcorehard_by
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...corehard_by
 
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019corehard_by
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019corehard_by
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019corehard_by
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019corehard_by
 

More from corehard_by (20)

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
 
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
 
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений ОхотниковC++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
 
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
 
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
 
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
 
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
 
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
 
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
 
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел ФилоновC++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
 
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan ČukićC++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
 
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
 

C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей Садовников

  • 1. Метаклассы: воплощаем мечты в реальность Сергей Садовников + + + + + + +
  • 2. Обо мне Сергей Садовников Архитектор ПО в компании “Лаборатория Касперского” corehard.by 01 CoreHard. Метаклассы: воплощаем мечты в реальность
  • 3. Метаклассы - что это? CoreHard. Метаклассы: воплощаем мечты в реальность 02 https://www.youtube.com/watch?v=6nsyX37nsRs
  • 4. Метаклассы - что это? CoreHard. Метаклассы: воплощаем мечты в реальность 03 https://www.youtube.com/watch?v=6nsyX37nsRs
  • 5. Метаклассы - что это? ● Новая языковая сущность ● Управляет генерацией AST и кода ● “Метапрограммирование” в императивном стиле ● Потенциальная замена макросам и некоторым шаблонам CoreHard. Метаклассы: воплощаем мечты в реальность 04
  • 6. Метаклассы - зачем? CoreHard. Метаклассы: воплощаем мечты в реальность 05 https://www.youtube.com/watch?v=80BZxujhY38
  • 7. Метаклассы - зачем? Основное назначение: 1. Ещё одна степень обобщения: описывать общие свойства целых групп классов (“interface”, “value”, “property” и т. д.), создавать библиотеки метаклассов 2. “Концепты на стероидах”: позволяют верифицировать свойства классов в императивном стиле 3. Inplace-расширение компилятора (и языка): непосредственная манипуляция AST на этапе компиляции с целью привести объявление класса к нужному виду (задание новых свойств, добавление методов, перегрузка операторов и т. п. CoreHard. Метаклассы: воплощаем мечты в реальность 06 Базируются на: 1. Static reflection (p0712) 2. Generative metaprogramming: code generation and injection (p0712, Code generation in C++) Описано в p0707 (revision 3)
  • 8. Метаклассы - пример struct IEnumerator : public IUnknown { virtual ~IEnumerator() {} virtual HRESULT Reset() = 0; virtual HRESULT MoveNext(BOOL* succeeded) = 0; virtual HRESULT Current(IUnknown** item) = 0; }; CoreHard. Метаклассы: воплощаем мечты в реальность 07
  • 9. Метаклассы - пример interface IEnumerator { void Reset(); BOOL MoveNext(); IUnknown* Current(); }; CoreHard. Метаклассы: воплощаем мечты в реальность 08
  • 10. Метаклассы - пример interface IEnumerator { void Reset(); BOOL MoveNext(); IUnknown* Current(); }; CoreHard. Метаклассы: воплощаем мечты в реальность 09 Метакласс
  • 11. Метаклассы - пример $class interface { virtual ~interface() {} constexpr { compiler.require($interface.variables().empty(), "interfaces may not contain data"); for (auto f : $interface.functions()) { compiler.require(!f.is_copy() && !f.is_move(), "interfaces may not copy or move; consider a virtual clone() instead"); if (!f.has_access()) f.make_public(); compiler.require(f.is_public(), "interface functions must be public"); f.make_pure_virtual(); f.parameters().add($f.return_type() *); f.set_type(HRESULT); f.bases().push_front(IUnknown); } } }; CoreHard. Метаклассы: воплощаем мечты в реальность 10
  • 12. Метаклассы - пример $class interface { virtual ~interface() {} constexpr { compiler.require($interface.variables().empty(), "interfaces may not contain data"); for (auto f : $interface.functions()) { compiler.require(!f.is_copy() && !f.is_move(), "interfaces may not copy or move; consider a virtual clone() instead"); if (!f.has_access()) f.make_public(); compiler.require(f.is_public(), "interface functions must be public"); f.make_pure_virtual(); f.parameters().add($f.return_type() *); f.set_type(HRESULT); f.bases().push_front(IUnknown); } } }; CoreHard. Метаклассы: воплощаем мечты в реальность 11 interface IEnumerator { void Reset(); BOOL MoveNext(); IUnknown* Current(); }; struct IEnumerator : public IUnknown { virtual ~IEnumerator() {} virtual HRESULT Reset() = 0; virtual HRESULT MoveNext(BOOL* succeeded) = 0; virtual HRESULT Current(IUnknown** item) = 0; };
  • 13. Метаклассы - пример $class interface { virtual ~interface() {} constexpr { compiler.require($interface.variables().empty(), "interfaces may not contain data"); for (auto f : $interface.functions()) { compiler.require(!f.is_copy() && !f.is_move(), "interfaces may not copy or move; consider a virtual clone() instead"); if (!f.has_access()) f.make_public(); compiler.require(f.is_public(), "interface functions must be public"); f.make_pure_virtual(); f.parameters().add($f.return_type() *); f.set_type(HRESULT); f.bases().push_front(IUnknown); } } }; CoreHard. Метаклассы: воплощаем мечты в реальность 12 В соответствии с p0707r1/p0707r2
  • 14. Метаклассы - пример template<typename T, typename S> constexpr void interface(T target, const S source) { compiler.require(source.variables().empty(), "interfaces may not contain data"); for (auto f : source.member_functions()) { compiler.require(!f.is_copy() && !f.is_move(), "interfaces may not copy or move; consider a virtual clone() instead"); if (!f.has_access()) f.make_public(); compiler.require(f.is_public(), "interface functions must be public"); auto ret = f.return_type(); if (ret == $void) { -> (target) class { virtual HRESULT idexpr(f)(__inject(f.parameters())) = 0; }; } else { -> (target) class { virtual HRESULT idexpr(f)(__inject(f.parameters()), typename(ret)* retval) = 0; }; } } } CoreHard. Метаклассы: воплощаем мечты в реальность 13 В соответствии с p0707r3
  • 15. Метаклассы - пример constexpr void basic_enum(meta::type target, const meta::type source) { value(target, source); // a basic_enum is-a value compiler.require(source.variables().size() > 0, "an enum cannot be empty"); if (src.variables().front().type().is_auto()) ->(target) { using U = int; } // underlying type else ->(target) { using U = (src.variables().front().type())$; } for (auto o : source.variables()) { if (!o.has_access()) o.make_public(); if (!o.has_storage()) o.make_constexpr(); if (o.has_auto_type()) o.set_type(U); compiler.require(o.is_public(), "enumerators must be public"); compiler.require(o.is_constexpr(), "enumerators must be constexpr"); compiler.require(o.type() == U, "enumerators must use same type"); ->(target) o; } ->(target) { U value; } // the instance value compiler.require(source.functions().empty(), "enumerations must not have functions"); compiler.require(source.bases().empty(), "enumerations must not have base classes"); } CoreHard. Метаклассы: воплощаем мечты в реальность 14
  • 16. Метаклассы Проблемы: ● Базируется на ещё не принятых пропозалах -> предлагаемый синтаксис может меняться ● Неизвестно, когда всё это примут. По некоторым оценкам - не раньше C++2z ● Не все возможные варианты использования детально рассмотрены в публично доступных документах CoreHard. Метаклассы: воплощаем мечты в реальность 15
  • 17. Метаклассы Проблемы: ● Базируется на ещё не принятых пропозалах -> предлагаемый синтаксис может меняться ● Неизвестно, когда всё это примут. По некоторым оценкам - не раньше C++2z ● Не все возможные варианты использования детально рассмотрены в публично доступных документах CoreHard. Метаклассы: воплощаем мечты в реальность 16 А если хочется раньше? ● Ждать принятия в стандарт и поддержки компиляторами ● Использовать шаблонную магию и макросы ● Реализовать и использовать сторонние утилиты
  • 18. Метаклассы Проблемы: ● Базируется на ещё не принятых пропозалах -> предлагаемый синтаксис может меняться ● Неизвестно, когда всё это примут. По некоторым оценкам - не раньше C++2z ● Не все возможные варианты использования детально рассмотрены в публично доступных документах CoreHard. Метаклассы: воплощаем мечты в реальность 17 А если хочется раньше? ● Ждать принятия в стандарт и поддержки компиляторами ● Использовать шаблонную магию и макросы ● Реализовать и использовать сторонние утилиты
  • 19. Метаклассы - сторонняя утилита Достоинства: ● Не требуется особой поддержки со стороны компиляторов ● Реализация в рамках актуальных стандартов ● Может быть легко встроена в сборочный тулчейн ● Может сделать кодовую базу проектов проще и упростить поддержку CoreHard. Метаклассы: воплощаем мечты в реальность 18
  • 20. Метаклассы - сторонняя утилита Достоинства: ● Не требуется особой поддержки со стороны компиляторов ● Реализация в рамках актуальных стандартов ● Может быть легко встроена в сборочный тулчейн ● Может сделать кодовую базу проектов проще и упростить поддержку CoreHard. Метаклассы: воплощаем мечты в реальность 19 Недостатки: ● Не соответствует одной из целей создания метаклассов (“Eliminate the need to invent non-C++ “side languages” and special compilers, such as Qt moc, COM MIDL, and C++/CX”) ● Собственный “птичий” язык для описания специальных конструкций ● Не всегда удобное использование предлагаемых возможностей ● Потенциальная несовместимость с итоговым вариантом пропозала
  • 21. Метаклассы - сторонняя утилита Основные возможности: ● Позволяет объявлять метаклассы ● Позволяет объявлять инстансы конкретных метаклассов ● В метаклассах позволяет проверять свойства инстансов и генерировать диагностику ● Позволяет внедрять в инстансы метаклассов новый код/изменять существующий ● Всё это в рамках одной кодовой базы CoreHard. Метаклассы: воплощаем мечты в реальность 20 Требования: ● Совместимость со стандартами C++14/17 (идеально - с C++11) ● Совместимость с популярными компиляторами (gcc/clang/MSVC) ● Лёгкость интеграции в сборочный тулчейн ● Относительная простота использования возможностей ● C++ на входе - C++ на выходе, ничего больше
  • 22. Метаклассы - сторонняя утилита Основная идея реализации: CoreHard. Метаклассы: воплощаем мечты в реальность 21 Metaclass declaration header Metaclass instance header Metaclasses processing tool .h-file with processed metaclass instance .cpp-file with processed metaclass instance
  • 23. Метаклассы - использование утилиты $_metaclass(Interface) { static void GenerateDecl() { compiler.message("Hello world from metaprogrammer!"); compiler.require($Interface.variables().empty(), "Interface may not contain data members"); $_inject(public) { enum {InterfaceId = 100500}; } for (auto& f : $Interface.functions()) { compiler.require(f.is_implicit() || (!f.is_copy_ctor() && !f.is_move_ctor()), "Interface can't contain copy or move constructor"); compiler.require(f.is_public(), "Inteface function must be public"); f.make_pure_virtual(); } } }; CoreHard. Метаклассы: воплощаем мечты в реальность 22
  • 24. Метаклассы - использование утилиты $_metaclass(Interface) { static void GenerateDecl() { compiler.message("Hello world from metaprogrammer!"); compiler.require($Interface.variables().empty(), "Interface may not contain data members"); $_inject(public) { enum {InterfaceId = 100500}; } for (auto& f : $Interface.functions()) { compiler.require(f.is_implicit() || (!f.is_copy_ctor() && !f.is_move_ctor()), "Interface can't contain copy or move constructor"); compiler.require(f.is_public(), "Inteface function must be public"); f.make_pure_virtual(); } } }; CoreHard. Метаклассы: воплощаем мечты в реальность 23 Макрос для объявление метакласса Метод, отвечающий за генерацию декларации Интерфейс к “компилятору” Макрос для внедрения нового кода в класс Ссылка на обрабатываемый инстанс метакласса
  • 25. Метаклассы - использование утилиты $_class(TestIface, Interface) { void TestMethod1(); std::string TestMethod2(int param) const; }; CoreHard. Метаклассы: воплощаем мечты в реальность 24
  • 26. Метаклассы - использование утилиты $_class(TestIface, Interface) { void TestMethod1(); std::string TestMethod2(int param) const; }; CoreHard. Метаклассы: воплощаем мечты в реальность 25 $_metaclass(Interface) { static void GenerateDecl() { compiler.message("Hello world from metaprogrammer!"); compiler.require($Interface.variables().empty(), "Interface may not contain data members"); $_inject(public) { enum {InterfaceId = 100500}; } for (auto& f : $Interface.functions()) { compiler.require(f.is_implicit() || (!f.is_copy_ctor() && !f.is_move_ctor()), "Interface can't contain copy or move constructor"); compiler.require(f.is_public(), "Inteface function must be public"); f.make_pure_virtual(); } } }; class TestIface { public: enum { InterfaceId = 100500 }; virtual void TestMethod1() = 0; virtual std::string TestMethod2(int param) const = 0; protected: private: };
  • 27. Метаклассы - использование утилиты struct TestStruct { int a; std::string b; template <typename Arch> void serialize(Arch &ar, unsigned int ver) { ar & a; ar & b; } }; CoreHard. Метаклассы: воплощаем мечты в реальность 26
  • 28. Метаклассы - использование утилиты struct TestStruct { int a; std::string b; template <typename Arch> void serialize(Arch &ar, unsigned int ver) { ar & a; ar & b; } }; CoreHard. Метаклассы: воплощаем мечты в реальность 27 struct AnotherTestStruct1 { // Members template <typename Arch> void serialize(Arch &ar, unsigned int ver) { // Serializer impl } }; struct AnotherTestStruct2 { // Members template <typename Arch> void serialize(Arch &ar, unsigned int ver) { // Serializer impl } }; struct AnotherTestStruct3 { // Members template <typename Arch> void serialize(Arch &ar, unsigned int ver) { // Serializer impl } }; struct AnotherTestStruct4 { // Members template <typename Arch> void serialize(Arch &ar, unsigned int ver) { // Serializer impl } }; struct AnotherTestStruct5 { // Members template <typename Arch> void serialize(Arch &ar, unsigned int ver) { // Serializer impl } };
  • 29. Метаклассы - использование утилиты $_struct(TestStruct, BoostSerializable) { int a; std::string b; }; CoreHard. Метаклассы: воплощаем мечты в реальность 28
  • 30. Метаклассы - использование утилиты $_metaclass(BoostSerializable) { static void GenerateDecl() { $_inject(public) [&, name="serialize"](auto& ar, const unsigned int ver) -> void { $_constexpr for (auto& v : $BoostSerializable.variables()) $_inject(_) ar & $_v(v.name()); }; } }; CoreHard. Метаклассы: воплощаем мечты в реальность 29
  • 31. Метаклассы - использование утилиты $_struct(TestStruct, BoostSerializable) { int a; std::string b; }; CoreHard. Метаклассы: воплощаем мечты в реальность 30 $_metaclass(BoostSerializable) { static void GenerateDecl() { $_inject(public) [&, name="serialize"](auto& ar, const unsigned int ver) -> void { $_constexpr for (auto& v : $BoostSerializable.variables()) $_inject(_) ar & $_v(v.name()); }; } }; class TestStruct { public: template <typename T0> void serialize(T0 &ar, const unsigned int ver) { ar & a; ar & b; } int a; std::string b; };
  • 32. Метаклассы - использование утилиты $_metaclass(BoostSerializableSplitted) { static void GenerateDecl() { $_inject(public) [&, name="load"](auto& ar, unsigned int ver) -> void { $_constexpr for (auto& v : $BoostSerializableSplitted.variables()) $_inject(_) ar >> $_v(v.name()); }; $_inject(public) [&, name="save", is_const=true](auto& ar, unsigned int ver) -> void { $_constexpr for (auto& v : $BoostSerializableSplitted.variables()) $_inject(_) ar << $_v(v.name()); }; $_inject(public) [&, name="serialize"](auto& ar, const unsigned int ver) -> void { boost::serialization::split_member(ar, $_safe(*this), ver); }; } }; CoreHard. Метаклассы: воплощаем мечты в реальность 31
  • 33. Метаклассы - использование утилиты class TestStruct { public: template <typename T0> void load(T0 &ar, unsigned int ver) { ar << a; ar << b; } template <typename T0> void save(T0 &ar, unsigned int ver) const { ar >> a; ar >> b; } template <typename T0> void serialize(T0 &ar, const unsigned int ver) { boost::serialization::split_member(ar, *this, ver); } int a; std::string b; protected: private: }; CoreHard. Метаклассы: воплощаем мечты в реальность 32
  • 34. Метаклассы - использование утилиты $_metaclass(Name) - макрос, с помощью которого объявляется метакласс $_class(Name, MetaclassName) - макрос, с помощью которого объявляется инстанс метакласса $_inject(Visibility) - макрос-префикс, который приводит к вставке следующего за ним блока в тело инстанса метакласса $_constexpr() - макрос-префикс, помечающий следующий за ним оператор как вычисляемый на этапе компиляции $_inject_xxx(Name, Visibility), где XXX - это enum, struct, class или union - макрос-префикс, который приводит к вставке следующего за ним блока в тело инстанса метакласса в виде отдельной структуры, enum’а, класса или объединения $_n(expr) - макрос, который заменяется значением выражения expr, вычисленного на этапе компиляции $_t(expr) - макрос, который заменяется типом выражения expr, вычисленного на этапе компиляции $_safe(expr) - макрос, который заменяется на expr CoreHard. Метаклассы: воплощаем мечты в реальность 33
  • 35. Метаклассы - использование утилиты compiler - экземпляр класса meta::CompilerImpl, предоставляющий доступ к глобальным методам типа require, error, message и т. п. meta::TypeInfo - класс, предоставляющий различную информацию о конкретном типе meta::MemberInfo - класс, предоставляющий различную информацию о конкретном члене класса meta::MethodInfo - класс, предоставляющий различную информацию о конкретном методе класса meta::ClassInfo - класс, предоставляющий различную информацию о конкретном классе. Видимые в методах реализации метакласса переменные вида $Interface - именно этого типа CoreHard. Метаклассы: воплощаем мечты в реальность 34
  • 36. Метаклассы - использование утилиты Перечисленные типы (и переменные), по сути - read/write-интерфейс к AST и компилятору CoreHard. Метаклассы: воплощаем мечты в реальность 35
  • 37. Metaclasses processing tool Metaclasses processing tool CoreHard. Метаклассы: воплощаем мечты в реальность 36 Metaclass declaration Metaclass instance clang frontend AST header file source file diagnostic output metaclasses processor Sources Messages
  • 38. Metaclasses processing tool CoreHard. Метаклассы: воплощаем мечты в реальность 37 C++ interpreter Source code clang frontend/AST matcher .h file .cpp file diagnostic output AST reflector Source code generator
  • 39. Интерпретатор C++ 1. Детально анализирует AST декларации метакласса 2. Фактически исполняет код декларации метакласса используя в качестве исходных данных отрефлексированный AST конкретного инстанса 3. Обеспечивает печать диагностических сообщений и проверку предикатов 4. Модифицирует отрефлексированный AST в соответствии с прописанной в меткалассе логикой 5. Инжектирует в инстанс метакласса заданные фрагменты кода с учётом constexpr- конструкций CoreHard. Метаклассы: воплощаем мечты в реальность 38
  • 40. Интерпретатор C++ CoreHard. Метаклассы: воплощаем мечты в реальность 39 Анализатор и интерпретатор операторов Вычислитель выражений Интерфейс к внутренней инфраструктуре
  • 41. Интерпретатор C++ compiler.require($Interface.variables().empty(), "Interface may not contain data members"); CoreHard. Метаклассы: воплощаем мечты в реальность 39
  • 42. Интерпретатор C++ compiler.require($Interface.variables().empty(), "Interface may not contain data members"); CoreHard. Метаклассы: воплощаем мечты в реальность 40 1. Интерпретатор операторов определяет, что это выражение
  • 43. Интерпретатор C++ compiler.require($Interface.variables().empty(), "Interface may not contain data members"); CoreHard. Метаклассы: воплощаем мечты в реальность 41 1. Интерпретатор операторов определяет, что это выражение 2. Вычислитель определяет, что выражение - это вызов члена класса
  • 44. Интерпретатор C++ compiler.require($Interface.variables().empty(), "Interface may not contain data members"); CoreHard. Метаклассы: воплощаем мечты в реальность 42 1. Интерпретатор операторов определяет, что это выражение 2. Вычислитель определяет, что выражение - это вызов члена класса 3. Объект, к которому применяется вызов метода, отображается на реализацию интерфейса к компилятору
  • 45. Интерпретатор C++ compiler.require($Interface.variables().empty(), "Interface may not contain data members"); CoreHard. Метаклассы: воплощаем мечты в реальность 43 1. Интерпретатор операторов определяет, что это выражение 2. Вычислитель определяет, что выражение - это вызов члена класса 3. Объект, к которому применяется вызов метода, отображается на реализацию интерфейса к компилятору 4. Начинают вычисляться параметры
  • 46. Интерпретатор C++ compiler.require($Interface.variables().empty(), "Interface may not contain data members"); CoreHard. Метаклассы: воплощаем мечты в реальность 44 1. Интерпретатор операторов определяет, что это выражение 2. Вычислитель определяет, что выражение - это вызов члена класса 3. Объект, к которому применяется вызов метода, отображается на реализацию интерфейса к компилятору 4. Начинают вычисляться параметры 5. Первый параметр - вызов члена класса
  • 47. Интерпретатор C++ compiler.require($Interface.variables().empty(), "Interface may not contain data members"); CoreHard. Метаклассы: воплощаем мечты в реальность 45 1. Интерпретатор операторов определяет, что это выражение 2. Вычислитель определяет, что выражение - это вызов члена класса 3. Объект, к которому применяется вызов метода, отображается на реализацию интерфейса к компилятору 4. Начинают вычисляться параметры 5. Первый параметр - вызов члена класса 6. ‘$Interface’ отображается на дескриптор инстанса метакласса
  • 48. Интерпретатор C++ compiler.require($Interface.variables().empty(), "Interface may not contain data members"); CoreHard. Метаклассы: воплощаем мечты в реальность 46 1. Интерпретатор операторов определяет, что это выражение 2. Вычислитель определяет, что выражение - это вызов члена класса 3. Объект, к которому применяется вызов метода, отображается на реализацию интерфейса к компилятору 4. Начинают вычисляться параметры 5. Первый параметр - вызов члена класса 6. ‘$Interface’ отображается на дескриптор инстанса метакласса 7. Последовательно вызываются: метод, возвращающий коллекцию переменных, а затем - ‘empty()’
  • 49. Интерпретатор C++ compiler.require($Interface.variables().empty(), "Interface may not contain data members"); CoreHard. Метаклассы: воплощаем мечты в реальность 47 1. Интерпретатор операторов определяет, что это выражение 2. Вычислитель определяет, что выражение - это вызов члена класса 3. Объект, к которому применяется вызов метода, отображается на реализацию интерфейса к компилятору 4. Начинают вычисляться параметры 5. Первый параметр - вызов члена класса 6. ‘$Interface’ отображается на дескриптор инстанса метакласса 7. Последовательно вызываются: метод, возвращающий коллекцию переменных, а затем - ‘empty()’ 8. Второй параметр, строковый литерал, конвертируется в строку
  • 50. Интерпретатор C++ compiler.require($Interface.variables().empty(), "Interface may not contain data members"); CoreHard. Метаклассы: воплощаем мечты в реальность 48 1. Интерпретатор операторов определяет, что это выражение 2. Вычислитель определяет, что выражение - это вызов члена класса 3. Объект, к которому применяется вызов метода, отображается на реализацию интерфейса к компилятору 4. Начинают вычисляться параметры 5. Первый параметр - вызов члена класса 6. ‘$Interface’ отображается на дескриптор инстанса метакласса 7. Последовательно вызываются: метод, возвращающий коллекцию переменных, а затем - ‘empty()’ 8. Второй параметр, строковый литерал, конвертируется в строку 9. Вызывается метод ‘require’, который в зависимости от значения первого параметра либо выводит диагностическое сообщение, либо нет
  • 51. Интерпретатор C++ Нюансы реализации: ● ОЧЕНЬ СЛОЖНОЕ И ПОДРОБНОЕ AST ● Необходимость следить за областями видимости и, соответственно, временем жизни объектов и промежуточных результатов вычислений ● Логика вычисления некоторых конструкций нетривиальна. Например, range-based for loop ● Необходимость отделять то, что нужно интерпретировать, от того, что нужно инжектировать в результирующий код CoreHard. Метаклассы: воплощаем мечты в реальность 49
  • 52. Интерпретатор C++ ● Связка boost::variant + boost::apply_visitor + C++14 + SFINAE - очень мощная. Позволяет упростить ряд конструкций. ● Атрибуты, введённые в язык, очень сильно помогают в разметке узлов AST и их последующем анализе ● Нет видимой необходимости поддерживать весь набор базовых типов в C++ CoreHard. Метаклассы: воплощаем мечты в реальность 50
  • 53. Интеграция с системой сборки include_directories( ${CODEGEN_DIR} ${CODEGEN_ROOT_DIR}/include ) set (CODEGEN_DIR ${CMAKE_CURRENT_BINARY_DIR}/codegen) file (MAKE_DIRECTORY ${CODEGEN_DIR}/generated) set (METACLASSES_GEN_FILE ${CODEGEN_DIR}/generated/structs.meta.h) set (CODEGEN_ROOT_DIR "d:/projects/work/Personal/autoprogrammer/autoprogrammer") set (CODEGEN_TOOL "d:/projects/work/Personal/autoprogrammer/autoprogrammer-build/MSVC2015-Debug/fl-codegen.exe") add_custom_command(OUTPUT ${METACLASSES_GEN_FILE} COMMAND ${CODEGEN_TOOL} ARGS -gen-metaclasses -show-clang-diag -ohdr ${METACLASSES_GEN_FILE} -input ${CMAKE_CURRENT_SOURCE_DIR}/structs.h -- clang-cl -std=c++14 -x c++ ${CMAKE_CXX_FLAGS} -I ${CODEGEN_ROOT_DIR}/include -I ${BOOST_ROOT} MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/structs.h DEPENDS ${CODEGEN_BIN_NAME} serialization_metaclass.h COMMENT "Generating metaclasses implementation for ${CMAKE_CURRENT_SOURCE_DIR}/structs.h" ) add_executable(${PROJECT_NAME} "main.cpp" "serialization_metaclass.h" "structs.h" ${METACLASSES_GEN_FILE}) target_link_libraries(${PROJECT_NAME} Boost::serialization) CoreHard. Метаклассы: воплощаем мечты в реальность 51
  • 54. Интеграция с системой сборки include_directories( ${CODEGEN_DIR} ${CODEGEN_ROOT_DIR}/include ) set (CODEGEN_DIR ${CMAKE_CURRENT_BINARY_DIR}/codegen) file (MAKE_DIRECTORY ${CODEGEN_DIR}/generated) set (METACLASSES_GEN_FILE ${CODEGEN_DIR}/generated/structs.meta.h) set (CODEGEN_ROOT_DIR "d:/projects/work/Personal/autoprogrammer/autoprogrammer") set (CODEGEN_TOOL "d:/projects/work/Personal/autoprogrammer/autoprogrammer-build/MSVC2015-Debug/fl-codegen.exe") add_custom_command(OUTPUT ${METACLASSES_GEN_FILE} COMMAND ${CODEGEN_TOOL} ARGS -gen-metaclasses -ohdr ${METACLASSES_GEN_FILE} -input ${CMAKE_CURRENT_SOURCE_DIR}/structs.h -- clang-cl -std=c++14 -x c++ ${CMAKE_CXX_FLAGS} -I ${CODEGEN_ROOT_DIR}/include -I ${BOOST_ROOT} MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/structs.h DEPENDS ${CODEGEN_BIN_NAME} serialization_metaclass.h COMMENT "Generating metaclasses implementation for ${CMAKE_CURRENT_SOURCE_DIR}/structs.h" ) add_executable(${PROJECT_NAME} "main.cpp" "serialization_metaclass.h" "structs.h" ${METACLASSES_GEN_FILE}) target_link_libraries(${PROJECT_NAME} Boost::serialization) CoreHard. Метаклассы: воплощаем мечты в реальность 52
  • 55. Дальнейшие планы ● Доработка основных возможностей интерпретатора ● Отладка и настройка сборки под разные системы и компиляторы ● Докер-образы с уже установленной утилитой ● Расширение возможностей frontend’а: ○ манипуляция с типами ○ возможность генерации не только в .h-файлы, но и в .cpp ○ возможность задания нескольких метаклассов для одного инстанса ○ приведение в соответствие с последней (r4) ревизии p0707 CoreHard. Метаклассы: воплощаем мечты в реальность 53
  • 56. Полезные ссылки ● Пропозал по метаклассам: http://www.open- std.org/jtc1/sc22/wg21/docs/papers/2018/p0707r3.pdf ● Пропозал по static reflection (один из):http://www.open- std.org/jtc1/sc22/wg21/docs/papers/2017/p0712r0.pdf ● Доклад Герба Саттера с ACCU 2017: https://www.youtube.com/watch?v=6nsyX37nsRs ● Доклад Герба Саттера с CppCon 2018: https://www.youtube.com/watch?v=80BZxujhY38 ● Реализация metaclasses processing tool: https://github.com/flexferrum/autoprogrammer/tree/metaclasses ● Презентация по “автопрограммисту”: https://docs.google.com/presentation/d/1v0lJqkQVrDUbaKy7_79Vg67EcrNKpBB9yruZIvo8f0c/e dit?usp=sharing CoreHard. Метаклассы: воплощаем мечты в реальность 54
  • 57. + + + + + + + Спасибо! Вопросы? :) Сергей Садовников flexferrum@gmail.com +