SlideShare a Scribd company logo
1 of 59
Download to read offline
!1
Шаблоны C++ и базы данных
Сергей Федоров, ведущий разработчик
!2
План доклада или о чём вот это всё
00 ⎮ Зачем писать свой драйвер?
10 ⎮ Чтение и запись буферов полей
20 ⎮ Работа с записями БД
30 ⎮ Работа с набором данных
40 ⎮ Как это поможет мне?
50 ⎮ Вопросы и ответы
05 ⎮ API с «человеческим» лицом
!3
Что потрогаем
00 ⎮ Первичный шаблон без определения
10 ⎮ SFINAE для специализаций шаблонов
20 ⎮ Variadic templates
30 ⎮ Fold expressions
40 ⎮ Constexpr функции
50 ⎮ If constexpr
!4
Зачем это всё?
!5
Зачем писать свой драйвер?
00
!6
1.Это красиво
2.Асинхронно
3.Prepared statements
4.Бинарный протокол
Зачем писать свой драйвер?
!7
Текстовый протокол vs бинарный
100ns
10 000ns
Int 64, Read Int 64, Write Ts, Read Ts, Write
2 032ns1 678ns
1 173ns1 219ns
35ns
25ns21ns
14ns
binary text
Зачем писать свой драйвер?
!7
API с «человеческим» лицом
05
Отправка запросов
Обработка ответов
!8
Исполнение запросов
auto trx = cluster.Begin({});
trx.Execute("insert into foobar (foo, bar) values ($1, $2)", 42, "baz");
trx.Commit();
!9
Работа с результатами запроса
auto trx = cluster.Begin();
auto res = trx.Execute("select foo, bar from foobar where foo = $1", 42);
for (auto row : res) {
// process row
for (auto field : row) {
// process field
}
}
trx.Commit();
!10
Работа с результатами запроса
auto trx = cluster.Begin();
auto res = trx.Execute("select foo, bar from foobar where foo = $1", 42);
for (auto row : res) {
// process row
auto foo = row[0].As<int>();
auto bar = row[1].As<std::string>();
}
trx.Commit();
!11
Работа с результатами запроса
auto trx = cluster.Begin();
auto res = trx.Execute("select foo, bar from foobar where foo = $1", 42);
for (auto row : res) {
// process row
auto [foo, bar] = row.As<int, std::string>();
}
trx.Commit();
!12
Работа с результатами запроса
https://www.ietf.org/rfc/rfc3092.txt
struct FooBar { int foo; std::string bar; }; // RFC 3092
auto trx = cluster.Begin();
auto res = trx.Execute("select foo, bar from foobar where foo = $1", 42);
for (auto row : res) {
// process row
auto foobar = row.As<FooBar>();
}
trx.Commit();
!13
Работа с результатами запроса
struct FooBar { int foo; std::string bar; }; // RFC 3092
auto trx = cluster.Begin();
auto res = trx.Execute("select foo, bar from foobar where foo = $1", 42);
auto foobars = res.AsContainer<std::vector<FooBar>>();
trx.Commit();
!14
Как всё это
работает?
!15
Чтение и запись буферов отдельных
полей
10
fold expression и запись
Замена tag switching на if constexpr
Определение наличия специализации
SFINAE для специализаций
!16
Запись аргументов запроса
11
!17
Отправка запроса
!18
auto trx = cluster.Begin({});
trx.Execute("insert into foobar (foo, bar) values ($1, $2)", 42, "baz");
trx.Commit();
/// Execute statement with arbitrary parameters
/// Suspends coroutine for execution
/// @throws NotInTransaction, SyntaxError, ConstraintViolation,
/// InvalidParameterType
template <typename... Args>
ResultSet Transaction::Execute(const std::string& statement, Args const&... args) {
detail::QueryParameters params;
if constexpr (sizeof...(Args) > 0) {
params.Write(GetConnectionUserTypes(), args...);
}
return DoExecute(statement, params, {});
}
Запись параметров запроса
!19
template <typename... T>
void QueryParameters::Write(const UserTypes& types, const T&... args) {
(Write(types, args), ...);
}
Запись параметров запроса
!20
template <typename T>
void QueryParameters::Write(const UserTypes& types, const T& arg) {
static_assert(io::traits::kIsMappedToPg<T>,
"Type doesn't have a mapping to Postgres type");
WriteParamType(types, arg);
WriteNullable(types, arg, io::traits::IsNullable<T>{});
}
template <typename T>
void QueryParameters::WriteNullable(const UserTypes& types, const T& arg, std::true_type) {
using NullDetector = io::traits::GetSetNull<T>;
if (NullDetector::IsNull(arg)) {
WriteNull();
} else {
WriteData(types, arg);
}
}
template <typename T>
void QueryParameters::WriteNullable(const UserTypes& types, const T& arg, std::false_type) {
WriteData(types, arg);
}
Запись параметров запроса
!21
template <typename T>
void QueryParameters::Write(const UserTypes& types, const T& arg) {
static_assert(io::traits::kIsMappedToPg<T>,
"Type doesn't have a mapping to Postgres type");
WriteParamType(types, arg);
if constexpr (io::traits::kIsNullable<T>) {
using NullDetector = io::traits::GetSetNull<T>;
if (NullDetector::IsNull(arg)) {
WriteNull();
return;
}
}
WriteData(types, arg);
}
if constexpr
!22
Чтение записи по слогам полям
15
!23
Чтение полей в переменные
!24
auto trx = cluster.Begin({});
auto res = trx.Execute("select foo, bar from foobar where foo >= $1", 42);
for (auto row : res) {
auto foo = row[0].As<int>();
auto bar = row[1].As<std::string>();
}
trx.Commit();
Чтение полей в переменные
!25
auto trx = cluster.Begin({});
auto res = trx.Execute("select foo, bar from foobar where foo >= $1", 42);
for (auto row : res) {
int foo;
std::string bar;
row[0].To(foo);
row[1].To(bar);
}
trx.Commit();
/// Read the field's buffer into user-provided variable.
/// @throws FieldValueIsNull If the field is null and the C++ type is
/// not nullable.
template <typename T>
void Field::To(T&& val) const {
using ValueType = typename std::decay<T>::type;
auto fb = GetBuffer();
if (fb.is_null) {
if constexpr (io::traits::kIsNullable<ValueType>) {
using NullSetter = io::traits::GetSetNull<ValueType>;
NullSetter::SetNull(val);
} else {
throw FieldValueIsNull{field_index_};
}
} else {
Read(fb, std::forward<T>(val));
}
}
Чтение буфера поля записи
!26
Чтение буфера поля записи
template <typename T>
void Field::Read(const io::FieldBuffer& buffer, T&& val) const {
using ValueType = typename std::decay<T>::type;
static_assert(io::traits::kHasAnyParser<ValueType>,
"Type doesn't have any parsers defined");
if (buffer.format == io::DataFormat::kTextDataFormat) {
ReadText(buffer, std::forward<T>(val));
} else {
ReadBinary(buffer, std::forward<T>(val));
}
}
!27
Чтение буфера поля записи
template <typename T>
void Field::ReadBinary(const io::FieldBuffer& buffer, T&& val) const {
using ValueType = typename std::decay<T>::type;
if constexpr (io::traits::kHasBinaryParser<ValueType>) {
io::ReadBinary(buffer, std::forward<T>(val));
} else {
throw NoValueParser{::utils::GetTypeName<T>(),
io::DataFormat::kBinaryDataFormat};
}
}
!28
template <typename T>
void ReadBinary(const FieldBuffer& buffer, T&& value) {
using ValueType = std::decay_t<T>;
static_assert( traits::kHasBinaryParser<ValueType>,
"Type doesn't have a binary parser");
ReadBuffer<DataFormat::kBinaryDataFormat>(buffer, std::forward<T>(value));
}
template <DataFormat F, typename T>
void ReadBuffer(const FieldBuffer& buffer, T&& value) {
using ValueType = std::decay_t<T>;
static_assert((traits::kHasParser<ValueType, F>),
"Type doesn't have an appropriate parser");
using BufferReader = typename traits::IO<ValueType, F>::ParserType;
BufferReader{std::forward<T>(value)}(buffer);
}
Чтение буфера поля записи
!29
Система «свойств» (traits)
16
!30
IsNullable
!31
template <typename T>
struct IsNullable : std::false_type {};
template <typename T>
constexpr bool kIsNullable = IsNullable<T>::value;
template <typename T>
struct GetSetNull {
inline static bool IsNull(const T&) { return false; }
inline static void SetNull(T&) {
throw TypeCannotBeNull(::utils::GetTypeName<T>());
}
};
IsNullable
!32
template <typename T>
struct IsNullable<std::optional<T>> : std::true_type {};
template <typename T>
struct GetSetNull<std::optional<T>> {
using ValueType = std::optional<T>;
inline static bool IsNull(const ValueType& v) { return !!v; }
inline static void SetNull(ValueType& v) { ValueType().swap(v); }
};
Рабочие лошадки
/// @brief Primary template for Postgre buffer parser.
/// Specialisations must provide call operators that parse FieldBuffer.
template <typename T, DataFormat, typename Enable = ::utils::void_t<>>
struct BufferParser;
/// @brief Primary template for Postgre buffer formatter
/// Specialisations must provide call operators that write to a buffer.
template <typename T, DataFormat, typename Enable = ::utils::void_t<>>
struct BufferFormatter;
!33
Рабочие лошадки
namespace traits {
template <typename T, DataFormat F, typename Enable = ::utils::void_t<>>
struct Input {
using type = BufferParser<T, F>;
};
template <typename T, DataFormat F, typename Enable = ::utils::void_t<>>
struct Output {
using type = BufferFormatter<T, F>;
};
template <typename T, DataFormat F>
struct IO {
using ParserType = typename Input<T, F>::type;
using FormatterType = typename Output<T, F>::type;
};
} // namespace traits
!34
Вспомогательные свойства
template <typename T, DataFormat Format>
struct HasParser : utils::IsDeclComplete<typename IO<T, Format>::ParserType> {};
template <typename T, DataFormat Format>
struct HasFormatter
: utils::IsDeclComplete<typename IO<T, Format>::FormatterType> {};
template <typename T, DataFormat F>
struct CustomParserDefined : utils::IsDeclComplete<BufferParser<T, F>> {};
template <typename T>
using CustomBinaryParserDefined =
CustomParserDefined<T, DataFormat::kBinaryDataFormat>;
template <typename T>
constexpr bool kCustomBinaryParserDefined = CustomBinaryParserDefined<T>::value;
!35
Чёрная магия
namespace detail {
template <typename T, std::size_t = sizeof(T)>
std::true_type IsCompleteImpl(T*);
std::false_type IsCompleteImpl(...);
} // namespace detail
template <typename T>
using IsDeclComplete = decltype(detail::IsCompleteImpl(std::declval<T*>()));
!36
Примеры
17
!37
Специализации для bool
template <>
struct BufferParser<bool, DataFormat::kBinaryDataFormat> {
bool& value;
explicit BufferParser(bool& val) : value{val} {}
void operator()(const FieldBuffer& buf) {
if (buf.length != 1) {
throw InvalidInputBufferSize{buf.length, "for boolean type"};
}
value = *buf.buffer != 0;
}
};
template <>
struct BufferFormatter<bool, DataFormat::kBinaryDataFormat> {
bool value;
explicit BufferFormatter(bool val) : value(val) {}
template <typename Buffer>
void operator()(const UserTypes&, Buffer& buf) const {
buf.push_back(value ? 1 : 0);
}
};
!38
Специализация ввода/вывода для массивов
template <typename Container>
struct ArrayBinaryParser; // contents skipped
template <typename Container>
struct ArrayBinaryFormatter; // contents skipped
namespace traits {
template <typename T>
struct Input<T, DataFormat::kBinaryDataFormat,
std::enable_if_t<!detail::kCustomBinaryParserDefined<T> &&
io::detail::kEnableArrayParser<T>>> {
using type = io::detail::ArrayBinaryParser<T>;
};
template <typename T>
struct Output<T, DataFormat::kBinaryDataFormat,
std::enable_if_t<!detail::kCustomBinaryFormatterDefined<T> &&
io::detail::kEnableArrayFormatter<T>>> {
using type = io::detail::ArrayBinaryFormatter<T>;
};
!39
Работа с записями БД
20
Вычисление аргументов шаблонного аргумента шаблона
fold expressions и чтение
!40
Варианты использования
auto [foo, bar] = row.As<int, std::string>(); // 1
row.To(foo, bar); // 2
auto foobar = row.As<FooBar>(); // 3
row.To(foobar); // 4
!41
Реализация мечты
class Row {
public:
template <typename T>
void To(T&& val) const; // 1
template <typename T>
void To(T&& val, RowTag) const; // 2
template <typename T>
void To(T&& val, FieldTag) const; // 3
template <typename... T>
void To(T&&... val) const; // 4
};
!42
Реализация мечты
template <typename... T>
void Row::To(T&&... val) const {
if (sizeof...(T) > Size()) {
throw InvalidTupleSizeRequested(Size(), sizeof...(T));
}
detail::RowDataExtractor<T...>::ExtractValues(*this, std::forward<T>(val)...);
}
template <typename T>
void Row::To(T&& val, RowTag) const {
using ValueType = std::decay_t<T>;
static_assert(io::traits::kIsRowType<ValueType>,
"This type cannot be used as a row type");
using RowType = io::RowType<ValueType>;
using TupleType = typename RowType::TupleType;
detail::TupleDataExtractor<TupleType>::ExtractTuple(
*this, RowType::GetTuple(std::forward<T>(val)));
}
!43
Реализация мечты
template <typename IndexTuple, typename... T>
struct RowDataExtractorBase;
template <std::size_t... Indexes, typename... T>
struct RowDataExtractorBase<std::index_sequence<Indexes...>, T...> {
static void ExtractValues(const Row& row, T&&... val) {
(row[Indexes].To(std::forward<T>(val)), ...);
}
static void ExtractTuple(const Row& row, std::tuple<T...>& val) {
(row[Indexes].To(std::get<Indexes>(val)), ...);
}
static void ExtractTuple(const Row& row, std::tuple<T...>&& val) {
(row[Indexes].To(std::get<Indexes>(val)), ...);
}
};
!44
Реализация мечты
template <typename... T>
struct RowDataExtractor
: RowDataExtractorBase<std::index_sequence_for<T...>, T...> {};
template <typename T>
struct TupleDataExtractor;
template <typename... T>
struct TupleDataExtractor<std::tuple<T...>>
: RowDataExtractorBase<std::index_sequence_for<T...>, T...> {};
!45
Всё — tuple
21
(но это не точно)
!46
template <typename T>
void Row::To(T&& val, RowTag) const {
using ValueType = std::decay_t<T>;
static_assert(io::traits::kIsRowType<ValueType>,
"This type cannot be used as a row type");
using RowType = io::RowType<ValueType>;
using TupleType = typename RowType::TupleType;
detail::TupleDataExtractor<TupleType>::ExtractTuple(
*this, RowType::GetTuple(std::forward<T>(val)));
}
Так откуда же tuple?
!47
RowType
!48
template <typename T>
struct RowType : detail::RowTypeImpl<T, traits::kRowCategory<T>> {};
std::tuple — тратим меньше сил
!49
template <typename T>
struct RowTypeImpl<T, traits::RowCategoryType::kTuple> {
using ValueType = T;
using TupleType = T;
static TupleType& GetTuple(ValueType& v) { return v; }
static const TupleType& GetTuple(const ValueType& v) { return v; }
};
Интрузивный метод
class FooClass {
int foo;
std::string bar;
public:
auto Introspect() {
return std::tie(foo, bar);
}
};
namespace io {
template <typename T>
struct RowTypeImpl<T, traits::RowCategoryType::kIntrusiveIntrospection> {
using ValueType = T;
static auto GetTuple(ValueType& v) { return v.Introspect(); }
};
} // namespace io
!50
Волшебный метод
https://github.com/apolukhin/magic_get
#include <boost/pfr/precise.hpp>
struct FooBar {
int foo;
std::string bar;
};
namespace io {
template <typename T>
struct RowTypeImpl<T, traits::RowCategoryType::kAggregate> {
using ValueType = T;
static auto GetTuple(ValueType& v) {
return boost::pfr::structure_tie(v);
}
};
} // namespace io
!51
Работа с набором данных
30
if constexpr для особых случаев
!52
И чтобы совсем красиво
struct FooBar { int foo; std::string bar; }; // RFC 3092
auto trx = cluster.Begin();
auto res = trx.Execute("select foo, bar from foobar where foo = $1", 42);
auto foobars = res.AsContainer<std::vector<FooBar>>();
trx.Commit();
!53
Особый шаг
template <typename Container>
Container ResultSet::AsContainer() const {
using ValueType = typename Container::value_type;
Container c;
if constexpr (io::traits::kCanReserve<Container>) {
c.reserve(Size());
}
auto res = AsSetOf<ValueType>();
std::copy(res.begin(), res.end(), io::traits::Inserter(c));
return c;
}
!54
Как это поможет мне?
40
Рецепты
!55
Рецепты
Tag switching
Variadic recursion
Система парсеров
Вычислить параметр шаблона
Особое действие для типа
Наличие специализации
if constexpr
fold expression
Система «свойств» типов
Первичный шаблон без специализации
Свойство и if constexpr
Магия
!56
Вопросы и, возможно, ответы
50
Вопросы
Возможно ответы
!57
Спасибо
Сергей Федоров
Ведущий разработчик
ser-fedorov@yandex-team.ru
@zmij_r
https://github.com/zmij
!58

More Related Content

What's hot

Михаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияМихаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияYandex
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловSergey Platonov
 
алгоритмы stl
алгоритмы stlалгоритмы stl
алгоритмы stlmcroitor
 
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Yandex
 
Объектно-Ориентированное Программирование на 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
 
стандартная библиотека с++: введение
стандартная библиотека с++: введениестандартная библиотека с++: введение
стандартная библиотека с++: введениеmcroitor
 
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksMikhail Kurnosov
 
Михаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знанияМихаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знанияYandex
 
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014Python Meetup
 
Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Dima Dzuba
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IДмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IPlatonov Sergey
 
Объектно-ориентированное программирование. Лекции 9 и 10
Объектно-ориентированное программирование. Лекции 9 и 10Объектно-ориентированное программирование. Лекции 9 и 10
Объектно-ориентированное программирование. Лекции 9 и 10Dima Dzuba
 
Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська Tatyanazaxarova
 
Cpp/cli particularities
Cpp/cli particularitiesCpp/cli particularities
Cpp/cli particularitiesmcroitor
 
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.Roman Orlov
 

What's hot (20)

Михаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияМихаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знания
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
 
алгоритмы stl
алгоритмы stlалгоритмы stl
алгоритмы stl
 
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
 
Python: ввод и вывод
Python: ввод и выводPython: ввод и вывод
Python: ввод и вывод
 
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
Объектно-Ориентированное Программирование на C++, Лекции  3 и 4 Объектно-Ориентированное Программирование на C++, Лекции  3 и 4
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
 
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
 
стандартная библиотека с++: введение
стандартная библиотека с++: введениестандартная библиотека с++: введение
стандартная библиотека с++: введение
 
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
 
Михаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знанияМихаил Давыдов: JavaScript. Базовые знания
Михаил Давыдов: JavaScript. Базовые знания
 
Step cpp0201
Step cpp0201Step cpp0201
Step cpp0201
 
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
Быстрые конструкции в Python - Олег Шидловский, Python Meetup 26.09.2014
 
Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IДмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
 
Step cpp022
Step cpp022Step cpp022
Step cpp022
 
Объектно-ориентированное программирование. Лекции 9 и 10
Объектно-ориентированное программирование. Лекции 9 и 10Объектно-ориентированное программирование. Лекции 9 и 10
Объектно-ориентированное программирование. Лекции 9 и 10
 
Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська
 
Cpp/cli particularities
Cpp/cli particularitiesCpp/cli particularities
Cpp/cli particularities
 
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
 
Python. Обработка ошибок
Python. Обработка ошибокPython. Обработка ошибок
Python. Обработка ошибок
 

Similar to Шаблоны C++ и базы данных. Сергей Федоров. CoreHard Spring 2019

12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...Ontico
 
Развитие технологий генерации эксплойтов на основе анализа бинарного кода
Развитие технологий генерации эксплойтов на основе анализа бинарного кодаРазвитие технологий генерации эксплойтов на основе анализа бинарного кода
Развитие технологий генерации эксплойтов на основе анализа бинарного кодаPositive Hack Days
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Yandex
 
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...Alexey Paznikov
 
CiklumCPPSat24032012:SergeyBratus-GoogleProtocolBuffers
CiklumCPPSat24032012:SergeyBratus-GoogleProtocolBuffersCiklumCPPSat24032012:SergeyBratus-GoogleProtocolBuffers
CiklumCPPSat24032012:SergeyBratus-GoogleProtocolBuffersCiklum Ukraine
 
Tarantool: как обрабатывать 
1,5 млрд запросов в сутки?
Tarantool: как обрабатывать 
1,5 млрд запросов в сутки?Tarantool: как обрабатывать 
1,5 млрд запросов в сутки?
Tarantool: как обрабатывать 
1,5 млрд запросов в сутки?tfmailru
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU
 
Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMTech Talks @NSU
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castRoman Orlov
 
MySQL+HandlerSocket=NoSQL
MySQL+HandlerSocket=NoSQL MySQL+HandlerSocket=NoSQL
MySQL+HandlerSocket=NoSQL Sergey Xek
 
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++Pavel Tsukanov
 
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru GroupКак не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru GroupMail.ru Group
 
Python&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.byPython&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.byPython Meetup
 
Лекция 4. Строки, байты, файлы и ввод/вывод.
 Лекция 4. Строки, байты, файлы и ввод/вывод. Лекция 4. Строки, байты, файлы и ввод/вывод.
Лекция 4. Строки, байты, файлы и ввод/вывод.Roman Brovko
 
javascript
javascriptjavascript
javascriptsovest
 
javascript_part1
javascript_part1javascript_part1
javascript_part1sovest
 
Хранимые процедуры в NoSQL СУБД на примере Tarantool / Денис Линник (Mail.Ru)
Хранимые процедуры в NoSQL СУБД на примере Tarantool / Денис Линник (Mail.Ru)Хранимые процедуры в NoSQL СУБД на примере Tarantool / Денис Линник (Mail.Ru)
Хранимые процедуры в NoSQL СУБД на примере Tarantool / Денис Линник (Mail.Ru)Ontico
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Yandex
 
язык програмирования
язык програмированияязык програмирования
язык програмированияOlegmingalev1997
 

Similar to Шаблоны C++ и базы данных. Сергей Федоров. CoreHard Spring 2019 (20)

12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
 
Развитие технологий генерации эксплойтов на основе анализа бинарного кода
Развитие технологий генерации эксплойтов на основе анализа бинарного кодаРазвитие технологий генерации эксплойтов на основе анализа бинарного кода
Развитие технологий генерации эксплойтов на основе анализа бинарного кода
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
 
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
 
CiklumCPPSat24032012:SergeyBratus-GoogleProtocolBuffers
CiklumCPPSat24032012:SergeyBratus-GoogleProtocolBuffersCiklumCPPSat24032012:SergeyBratus-GoogleProtocolBuffers
CiklumCPPSat24032012:SergeyBratus-GoogleProtocolBuffers
 
Tarantool: как обрабатывать 
1,5 млрд запросов в сутки?
Tarantool: как обрабатывать 
1,5 млрд запросов в сутки?Tarantool: как обрабатывать 
1,5 млрд запросов в сутки?
Tarantool: как обрабатывать 
1,5 млрд запросов в сутки?
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVM
 
Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVM
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_cast
 
MySQL+HandlerSocket=NoSQL
MySQL+HandlerSocket=NoSQL MySQL+HandlerSocket=NoSQL
MySQL+HandlerSocket=NoSQL
 
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
 
C language. Introduction
C language. IntroductionC language. Introduction
C language. Introduction
 
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru GroupКак не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
 
Python&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.byPython&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.by
 
Лекция 4. Строки, байты, файлы и ввод/вывод.
 Лекция 4. Строки, байты, файлы и ввод/вывод. Лекция 4. Строки, байты, файлы и ввод/вывод.
Лекция 4. Строки, байты, файлы и ввод/вывод.
 
javascript
javascriptjavascript
javascript
 
javascript_part1
javascript_part1javascript_part1
javascript_part1
 
Хранимые процедуры в NoSQL СУБД на примере Tarantool / Денис Линник (Mail.Ru)
Хранимые процедуры в NoSQL СУБД на примере Tarantool / Денис Линник (Mail.Ru)Хранимые процедуры в NoSQL СУБД на примере Tarantool / Денис Линник (Mail.Ru)
Хранимые процедуры в NoSQL СУБД на примере Tarantool / Денис Линник (Mail.Ru)
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11
 
язык програмирования
язык програмированияязык програмирования
язык програмирования
 

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++ 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
 

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++ 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
 

Шаблоны C++ и базы данных. Сергей Федоров. CoreHard Spring 2019

  • 1. !1
  • 2. Шаблоны C++ и базы данных Сергей Федоров, ведущий разработчик !2
  • 3. План доклада или о чём вот это всё 00 ⎮ Зачем писать свой драйвер? 10 ⎮ Чтение и запись буферов полей 20 ⎮ Работа с записями БД 30 ⎮ Работа с набором данных 40 ⎮ Как это поможет мне? 50 ⎮ Вопросы и ответы 05 ⎮ API с «человеческим» лицом !3
  • 4. Что потрогаем 00 ⎮ Первичный шаблон без определения 10 ⎮ SFINAE для специализаций шаблонов 20 ⎮ Variadic templates 30 ⎮ Fold expressions 40 ⎮ Constexpr функции 50 ⎮ If constexpr !4
  • 6. Зачем писать свой драйвер? 00 !6
  • 7. 1.Это красиво 2.Асинхронно 3.Prepared statements 4.Бинарный протокол Зачем писать свой драйвер? !7
  • 8. Текстовый протокол vs бинарный 100ns 10 000ns Int 64, Read Int 64, Write Ts, Read Ts, Write 2 032ns1 678ns 1 173ns1 219ns 35ns 25ns21ns 14ns binary text Зачем писать свой драйвер? !7
  • 9. API с «человеческим» лицом 05 Отправка запросов Обработка ответов !8
  • 10. Исполнение запросов auto trx = cluster.Begin({}); trx.Execute("insert into foobar (foo, bar) values ($1, $2)", 42, "baz"); trx.Commit(); !9
  • 11. Работа с результатами запроса auto trx = cluster.Begin(); auto res = trx.Execute("select foo, bar from foobar where foo = $1", 42); for (auto row : res) { // process row for (auto field : row) { // process field } } trx.Commit(); !10
  • 12. Работа с результатами запроса auto trx = cluster.Begin(); auto res = trx.Execute("select foo, bar from foobar where foo = $1", 42); for (auto row : res) { // process row auto foo = row[0].As<int>(); auto bar = row[1].As<std::string>(); } trx.Commit(); !11
  • 13. Работа с результатами запроса auto trx = cluster.Begin(); auto res = trx.Execute("select foo, bar from foobar where foo = $1", 42); for (auto row : res) { // process row auto [foo, bar] = row.As<int, std::string>(); } trx.Commit(); !12
  • 14. Работа с результатами запроса https://www.ietf.org/rfc/rfc3092.txt struct FooBar { int foo; std::string bar; }; // RFC 3092 auto trx = cluster.Begin(); auto res = trx.Execute("select foo, bar from foobar where foo = $1", 42); for (auto row : res) { // process row auto foobar = row.As<FooBar>(); } trx.Commit(); !13
  • 15. Работа с результатами запроса struct FooBar { int foo; std::string bar; }; // RFC 3092 auto trx = cluster.Begin(); auto res = trx.Execute("select foo, bar from foobar where foo = $1", 42); auto foobars = res.AsContainer<std::vector<FooBar>>(); trx.Commit(); !14
  • 17. Чтение и запись буферов отдельных полей 10 fold expression и запись Замена tag switching на if constexpr Определение наличия специализации SFINAE для специализаций !16
  • 19. Отправка запроса !18 auto trx = cluster.Begin({}); trx.Execute("insert into foobar (foo, bar) values ($1, $2)", 42, "baz"); trx.Commit();
  • 20. /// Execute statement with arbitrary parameters /// Suspends coroutine for execution /// @throws NotInTransaction, SyntaxError, ConstraintViolation, /// InvalidParameterType template <typename... Args> ResultSet Transaction::Execute(const std::string& statement, Args const&... args) { detail::QueryParameters params; if constexpr (sizeof...(Args) > 0) { params.Write(GetConnectionUserTypes(), args...); } return DoExecute(statement, params, {}); } Запись параметров запроса !19
  • 21. template <typename... T> void QueryParameters::Write(const UserTypes& types, const T&... args) { (Write(types, args), ...); } Запись параметров запроса !20
  • 22. template <typename T> void QueryParameters::Write(const UserTypes& types, const T& arg) { static_assert(io::traits::kIsMappedToPg<T>, "Type doesn't have a mapping to Postgres type"); WriteParamType(types, arg); WriteNullable(types, arg, io::traits::IsNullable<T>{}); } template <typename T> void QueryParameters::WriteNullable(const UserTypes& types, const T& arg, std::true_type) { using NullDetector = io::traits::GetSetNull<T>; if (NullDetector::IsNull(arg)) { WriteNull(); } else { WriteData(types, arg); } } template <typename T> void QueryParameters::WriteNullable(const UserTypes& types, const T& arg, std::false_type) { WriteData(types, arg); } Запись параметров запроса !21
  • 23. template <typename T> void QueryParameters::Write(const UserTypes& types, const T& arg) { static_assert(io::traits::kIsMappedToPg<T>, "Type doesn't have a mapping to Postgres type"); WriteParamType(types, arg); if constexpr (io::traits::kIsNullable<T>) { using NullDetector = io::traits::GetSetNull<T>; if (NullDetector::IsNull(arg)) { WriteNull(); return; } } WriteData(types, arg); } if constexpr !22
  • 24. Чтение записи по слогам полям 15 !23
  • 25. Чтение полей в переменные !24 auto trx = cluster.Begin({}); auto res = trx.Execute("select foo, bar from foobar where foo >= $1", 42); for (auto row : res) { auto foo = row[0].As<int>(); auto bar = row[1].As<std::string>(); } trx.Commit();
  • 26. Чтение полей в переменные !25 auto trx = cluster.Begin({}); auto res = trx.Execute("select foo, bar from foobar where foo >= $1", 42); for (auto row : res) { int foo; std::string bar; row[0].To(foo); row[1].To(bar); } trx.Commit();
  • 27. /// Read the field's buffer into user-provided variable. /// @throws FieldValueIsNull If the field is null and the C++ type is /// not nullable. template <typename T> void Field::To(T&& val) const { using ValueType = typename std::decay<T>::type; auto fb = GetBuffer(); if (fb.is_null) { if constexpr (io::traits::kIsNullable<ValueType>) { using NullSetter = io::traits::GetSetNull<ValueType>; NullSetter::SetNull(val); } else { throw FieldValueIsNull{field_index_}; } } else { Read(fb, std::forward<T>(val)); } } Чтение буфера поля записи !26
  • 28. Чтение буфера поля записи template <typename T> void Field::Read(const io::FieldBuffer& buffer, T&& val) const { using ValueType = typename std::decay<T>::type; static_assert(io::traits::kHasAnyParser<ValueType>, "Type doesn't have any parsers defined"); if (buffer.format == io::DataFormat::kTextDataFormat) { ReadText(buffer, std::forward<T>(val)); } else { ReadBinary(buffer, std::forward<T>(val)); } } !27
  • 29. Чтение буфера поля записи template <typename T> void Field::ReadBinary(const io::FieldBuffer& buffer, T&& val) const { using ValueType = typename std::decay<T>::type; if constexpr (io::traits::kHasBinaryParser<ValueType>) { io::ReadBinary(buffer, std::forward<T>(val)); } else { throw NoValueParser{::utils::GetTypeName<T>(), io::DataFormat::kBinaryDataFormat}; } } !28
  • 30. template <typename T> void ReadBinary(const FieldBuffer& buffer, T&& value) { using ValueType = std::decay_t<T>; static_assert( traits::kHasBinaryParser<ValueType>, "Type doesn't have a binary parser"); ReadBuffer<DataFormat::kBinaryDataFormat>(buffer, std::forward<T>(value)); } template <DataFormat F, typename T> void ReadBuffer(const FieldBuffer& buffer, T&& value) { using ValueType = std::decay_t<T>; static_assert((traits::kHasParser<ValueType, F>), "Type doesn't have an appropriate parser"); using BufferReader = typename traits::IO<ValueType, F>::ParserType; BufferReader{std::forward<T>(value)}(buffer); } Чтение буфера поля записи !29
  • 32. IsNullable !31 template <typename T> struct IsNullable : std::false_type {}; template <typename T> constexpr bool kIsNullable = IsNullable<T>::value; template <typename T> struct GetSetNull { inline static bool IsNull(const T&) { return false; } inline static void SetNull(T&) { throw TypeCannotBeNull(::utils::GetTypeName<T>()); } };
  • 33. IsNullable !32 template <typename T> struct IsNullable<std::optional<T>> : std::true_type {}; template <typename T> struct GetSetNull<std::optional<T>> { using ValueType = std::optional<T>; inline static bool IsNull(const ValueType& v) { return !!v; } inline static void SetNull(ValueType& v) { ValueType().swap(v); } };
  • 34. Рабочие лошадки /// @brief Primary template for Postgre buffer parser. /// Specialisations must provide call operators that parse FieldBuffer. template <typename T, DataFormat, typename Enable = ::utils::void_t<>> struct BufferParser; /// @brief Primary template for Postgre buffer formatter /// Specialisations must provide call operators that write to a buffer. template <typename T, DataFormat, typename Enable = ::utils::void_t<>> struct BufferFormatter; !33
  • 35. Рабочие лошадки namespace traits { template <typename T, DataFormat F, typename Enable = ::utils::void_t<>> struct Input { using type = BufferParser<T, F>; }; template <typename T, DataFormat F, typename Enable = ::utils::void_t<>> struct Output { using type = BufferFormatter<T, F>; }; template <typename T, DataFormat F> struct IO { using ParserType = typename Input<T, F>::type; using FormatterType = typename Output<T, F>::type; }; } // namespace traits !34
  • 36. Вспомогательные свойства template <typename T, DataFormat Format> struct HasParser : utils::IsDeclComplete<typename IO<T, Format>::ParserType> {}; template <typename T, DataFormat Format> struct HasFormatter : utils::IsDeclComplete<typename IO<T, Format>::FormatterType> {}; template <typename T, DataFormat F> struct CustomParserDefined : utils::IsDeclComplete<BufferParser<T, F>> {}; template <typename T> using CustomBinaryParserDefined = CustomParserDefined<T, DataFormat::kBinaryDataFormat>; template <typename T> constexpr bool kCustomBinaryParserDefined = CustomBinaryParserDefined<T>::value; !35
  • 37. Чёрная магия namespace detail { template <typename T, std::size_t = sizeof(T)> std::true_type IsCompleteImpl(T*); std::false_type IsCompleteImpl(...); } // namespace detail template <typename T> using IsDeclComplete = decltype(detail::IsCompleteImpl(std::declval<T*>())); !36
  • 39. Специализации для bool template <> struct BufferParser<bool, DataFormat::kBinaryDataFormat> { bool& value; explicit BufferParser(bool& val) : value{val} {} void operator()(const FieldBuffer& buf) { if (buf.length != 1) { throw InvalidInputBufferSize{buf.length, "for boolean type"}; } value = *buf.buffer != 0; } }; template <> struct BufferFormatter<bool, DataFormat::kBinaryDataFormat> { bool value; explicit BufferFormatter(bool val) : value(val) {} template <typename Buffer> void operator()(const UserTypes&, Buffer& buf) const { buf.push_back(value ? 1 : 0); } }; !38
  • 40. Специализация ввода/вывода для массивов template <typename Container> struct ArrayBinaryParser; // contents skipped template <typename Container> struct ArrayBinaryFormatter; // contents skipped namespace traits { template <typename T> struct Input<T, DataFormat::kBinaryDataFormat, std::enable_if_t<!detail::kCustomBinaryParserDefined<T> && io::detail::kEnableArrayParser<T>>> { using type = io::detail::ArrayBinaryParser<T>; }; template <typename T> struct Output<T, DataFormat::kBinaryDataFormat, std::enable_if_t<!detail::kCustomBinaryFormatterDefined<T> && io::detail::kEnableArrayFormatter<T>>> { using type = io::detail::ArrayBinaryFormatter<T>; }; !39
  • 41. Работа с записями БД 20 Вычисление аргументов шаблонного аргумента шаблона fold expressions и чтение !40
  • 42. Варианты использования auto [foo, bar] = row.As<int, std::string>(); // 1 row.To(foo, bar); // 2 auto foobar = row.As<FooBar>(); // 3 row.To(foobar); // 4 !41
  • 43. Реализация мечты class Row { public: template <typename T> void To(T&& val) const; // 1 template <typename T> void To(T&& val, RowTag) const; // 2 template <typename T> void To(T&& val, FieldTag) const; // 3 template <typename... T> void To(T&&... val) const; // 4 }; !42
  • 44. Реализация мечты template <typename... T> void Row::To(T&&... val) const { if (sizeof...(T) > Size()) { throw InvalidTupleSizeRequested(Size(), sizeof...(T)); } detail::RowDataExtractor<T...>::ExtractValues(*this, std::forward<T>(val)...); } template <typename T> void Row::To(T&& val, RowTag) const { using ValueType = std::decay_t<T>; static_assert(io::traits::kIsRowType<ValueType>, "This type cannot be used as a row type"); using RowType = io::RowType<ValueType>; using TupleType = typename RowType::TupleType; detail::TupleDataExtractor<TupleType>::ExtractTuple( *this, RowType::GetTuple(std::forward<T>(val))); } !43
  • 45. Реализация мечты template <typename IndexTuple, typename... T> struct RowDataExtractorBase; template <std::size_t... Indexes, typename... T> struct RowDataExtractorBase<std::index_sequence<Indexes...>, T...> { static void ExtractValues(const Row& row, T&&... val) { (row[Indexes].To(std::forward<T>(val)), ...); } static void ExtractTuple(const Row& row, std::tuple<T...>& val) { (row[Indexes].To(std::get<Indexes>(val)), ...); } static void ExtractTuple(const Row& row, std::tuple<T...>&& val) { (row[Indexes].To(std::get<Indexes>(val)), ...); } }; !44
  • 46. Реализация мечты template <typename... T> struct RowDataExtractor : RowDataExtractorBase<std::index_sequence_for<T...>, T...> {}; template <typename T> struct TupleDataExtractor; template <typename... T> struct TupleDataExtractor<std::tuple<T...>> : RowDataExtractorBase<std::index_sequence_for<T...>, T...> {}; !45
  • 47. Всё — tuple 21 (но это не точно) !46
  • 48. template <typename T> void Row::To(T&& val, RowTag) const { using ValueType = std::decay_t<T>; static_assert(io::traits::kIsRowType<ValueType>, "This type cannot be used as a row type"); using RowType = io::RowType<ValueType>; using TupleType = typename RowType::TupleType; detail::TupleDataExtractor<TupleType>::ExtractTuple( *this, RowType::GetTuple(std::forward<T>(val))); } Так откуда же tuple? !47
  • 49. RowType !48 template <typename T> struct RowType : detail::RowTypeImpl<T, traits::kRowCategory<T>> {};
  • 50. std::tuple — тратим меньше сил !49 template <typename T> struct RowTypeImpl<T, traits::RowCategoryType::kTuple> { using ValueType = T; using TupleType = T; static TupleType& GetTuple(ValueType& v) { return v; } static const TupleType& GetTuple(const ValueType& v) { return v; } };
  • 51. Интрузивный метод class FooClass { int foo; std::string bar; public: auto Introspect() { return std::tie(foo, bar); } }; namespace io { template <typename T> struct RowTypeImpl<T, traits::RowCategoryType::kIntrusiveIntrospection> { using ValueType = T; static auto GetTuple(ValueType& v) { return v.Introspect(); } }; } // namespace io !50
  • 52. Волшебный метод https://github.com/apolukhin/magic_get #include <boost/pfr/precise.hpp> struct FooBar { int foo; std::string bar; }; namespace io { template <typename T> struct RowTypeImpl<T, traits::RowCategoryType::kAggregate> { using ValueType = T; static auto GetTuple(ValueType& v) { return boost::pfr::structure_tie(v); } }; } // namespace io !51
  • 53. Работа с набором данных 30 if constexpr для особых случаев !52
  • 54. И чтобы совсем красиво struct FooBar { int foo; std::string bar; }; // RFC 3092 auto trx = cluster.Begin(); auto res = trx.Execute("select foo, bar from foobar where foo = $1", 42); auto foobars = res.AsContainer<std::vector<FooBar>>(); trx.Commit(); !53
  • 55. Особый шаг template <typename Container> Container ResultSet::AsContainer() const { using ValueType = typename Container::value_type; Container c; if constexpr (io::traits::kCanReserve<Container>) { c.reserve(Size()); } auto res = AsSetOf<ValueType>(); std::copy(res.begin(), res.end(), io::traits::Inserter(c)); return c; } !54
  • 56. Как это поможет мне? 40 Рецепты !55
  • 57. Рецепты Tag switching Variadic recursion Система парсеров Вычислить параметр шаблона Особое действие для типа Наличие специализации if constexpr fold expression Система «свойств» типов Первичный шаблон без специализации Свойство и if constexpr Магия !56
  • 58. Вопросы и, возможно, ответы 50 Вопросы Возможно ответы !57