SlideShare a Scribd company logo
Метаклассы:
воплощаем мечты в реальность
Сергей Садовников
+
+ +
+
+
+
+
Обо мне
Сергей Садовников
Архитектор ПО в компании “Лаборатория
Касперского”
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
 
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 UsZFConf Conference
 
Scala: что, как и зачем?
Scala: что, как и зачем?Scala: что, как и зачем?
Scala: что, как и зачем?Roman Timushev
 
C++ осень 2012 лекция 9
C++ осень 2012 лекция 9C++ осень 2012 лекция 9
C++ осень 2012 лекция 9Technopark
 
Михаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знанияМихаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знанияYandex
 
Component Inspector
Component InspectorComponent Inspector
Component Inspector
Roman Dvornov
 
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 action
Yuri 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 Level
Nikita Lipsky
 
Теория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямТеория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциям
Sergey Staroletov
 
Как выглядит современный фронтенд
Как выглядит современный фронтендКак выглядит современный фронтенд
Как выглядит современный фронтенд
Timophy Chaptykov
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
Andrey 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
Корпоративное приложение на Rails
Andrei 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 Reflection
Denis 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 Kazakova
corehard_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 2019
corehard_by
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
corehard_by
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
corehard_by
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
corehard_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 +