SlideShare a Scribd company logo
1 of 170
Download to read offline
Antony Polukhin
Полухин Антон
C++ трюки из Такси
Содержание
●
Зачем нам это
●
Pimpl
●
Logging
●
Parse
Taxi C++ tricks
C++ :-(
C++ :-)
userver
Taxi C++ tricks
userver – framework для написания
высокопроизводительных приложений
Taxi C++ tricks 5 / 170
userver – framework для написания
высокопроизводительных приложений
Прост и удобен в использовании
Taxi C++ tricks 6 / 170
userver – framework для написания
высокопроизводительных приложений
Прост и удобен в использовании:
– Работа с форматами JSON/BSON/Yaml/…
Taxi C++ tricks 7 / 170
userver – framework для написания
высокопроизводительных приложений
Прост и удобен в использовании:
– Работа с форматами JSON/BSON/Yaml/…
– Логирование
Taxi C++ tricks 8 / 170
userver – framework для написания
высокопроизводительных приложений
Прост и удобен в использовании:
– Работа с форматами JSON/BSON/Yaml/…
– Логирование
– Сеть
Taxi C++ tricks 9 / 170
userver – framework для написания
высокопроизводительных приложений
Прост и удобен в использовании:
– Работа с форматами JSON/BSON/Yaml/…
– Логирование
– Сеть
– Драйвера Postgres/Mongo/…
Taxi C++ tricks 10 / 170
userver – framework для написания
высокопроизводительных приложений
Прост и удобен в использовании:
– Работа с форматами JSON/BSON/Yaml/…
– Логирование
– Сеть
– Драйвера Postgres/Mongo/…
– Корутины
Taxi C++ tricks 11 / 170
userver – framework для написания
высокопроизводительных приложений
Прост и удобен в использовании:
– Работа с форматами JSON/BSON/Yaml/…
– Логирование
– Сеть
– Драйвера Postgres/Mongo/…
– Корутины
– Кодогенерация
Taxi C++ tricks 12 / 170
userver – framework для написания
высокопроизводительных приложений
Прост и удобен в использовании:
– Работа с форматами JSON/BSON/Yaml/…
– Логирование
– Сеть
– Драйвера Postgres/Mongo/…
– Корутины
– Кодогенерация
– …
Taxi C++ tricks 13 / 170
userver – framework для написания
высокопроизводительных приложений
Прост и удобен в использовании:
– Работа с форматами JSON/BSON/Yaml/…
– Логирование
– Сеть
– Драйвера Postgres/Mongo/…
– Корутины
– Кодогенерация
– …
Очень-очень быстрый!
Taxi C++ tricks 14 / 170
userver – framework для написания
высокопроизводительных приложений
Прост и удобен в использовании:
– Работа с форматами JSON/BSON/Yaml/…
– Логирование
– Сеть
– Драйвера Postgres/Mongo/…
– Корутины
– Кодогенерация
– …
Очень-очень быстрый!
Taxi C++ tricks 15 / 170
userver Очень-очень быстрый!
Taxi C++ tricks 16 / 170
userver Очень-очень быстрый!
Зачастую привычные решения нам не подходят
Taxi C++ tricks 17 / 170
Pimpl
Taxi C++ tricks
Pimpl
#include <third_party/json.hpp>
namespace formats::json {
class Exception;
struct Value;
} // namespace formats::json
Taxi C++ tricks 19 / 170
Pimpl
#include <third_party/json.hpp>
struct Value {
Value() = default;
Value(Value&& other) = default;
Value& operator=(Value&& other) = default;
~Value() = default;
std::size_t Size() const { return data_.size(); }
private:
third_party::Json data_;
};
Taxi C++ tricks 20 / 170
Pimpl
#include <third_party/json.hpp>
struct Value {
Value() = default;
Value(Value&& other) = default;
Value& operator=(Value&& other) = default;
~Value() = default;
std::size_t Size() const { return data_.size(); }
private:
third_party::Json data_;
};
Taxi C++ tricks 21 / 170
Pimpl
#include <third_party/json.hpp>
struct Value {
Value() = default;
Value(Value&& other) = default;
Value& operator=(Value&& other) = default;
~Value() = default;
std::size_t Size() const { return data_.size(); }
private:
third_party::Json data_;
};
Taxi C++ tricks 22 / 170
Pimpl
#include <third_party/json.hpp> // PROBLEMS!
struct Value {
Value() = default;
Value(Value&& other) = default;
Value& operator=(Value&& other) = default;
~Value() = default;
std::size_t Size() const { return data_.size(); }
private:
third_party::Json data_;
};
Taxi C++ tricks 23 / 170
Pimpl
std::size_t Sample(const formats::json::Value& value) {
try {
return value.Size();
} catch (const third_party::Exception& e) {
LOG_ERROR() << e;
return kFallback;
}
}
Taxi C++ tricks 24 / 170
Pimpl
std::size_t Sample(const formats::json::Value& value) {
try {
return value.Size();
} catch (const third_party::Exception& e) {
LOG_ERROR() << e;
return kFallback;
}
}
Taxi C++ tricks 25 / 170
Pimpl
#include <third_party/json.hpp>
namespace formats::json {
class Exception;
struct Value;
} // namespace formats::json
Taxi C++ tricks 26 / 170
Pimpl
namespace third_party {
struct Json; // forward declaration
} // namespace third_party
namespace formats::json {
class Exception;
struct Value;
} // namespace formats::json
Taxi C++ tricks 27 / 170
Pimpl
#include <impl/json_fwd.hpp>
struct Value {
Value() = default;
Value(Value&& other) = default;
Value& operator=(Value&& other) = default;
~Value() = default;
std::size_t Size() const { return data_.size(); }
private:
third_party::Json data_;
};
Taxi C++ tricks 28 / 170
Pimpl
#include <impl/json_fwd.hpp>
struct Value {
Value() = default;
Value(Value&& other) = default;
Value& operator=(Value&& other) = default;
~Value() = default;
std::size_t Size() const { return data_.size(); }
private:
third_party::Json data_;
};
Taxi C++ tricks 29 / 170
Pimpl
#include <impl/json_fwd.hpp>
struct Value {
Value() = default;
Value(Value&& other) = default;
Value& operator=(Value&& other) = default;
~Value() = default;
std::size_t Size() const { return data_.size(); }
private:
third_party::Json data_;
};
Taxi C++ tricks 30 / 170
Pimpl
error: field 'data_' has incomplete type 'third_party::Json'
| third_party::Json data_;
Taxi C++ tricks 31 / 170
Pimpl
#include <impl/json_fwd.hpp>
struct Value {
Value() = default;
Value(Value&& other) = default;
Value& operator=(Value&& other) = default;
~Value() = default;
std::size_t Size() const { return data_.size(); }
private:
third_party::Json data_;
};
Taxi C++ tricks 32 / 170
Pimpl
#include <impl/json_fwd.hpp>
struct Value {
Value();
Value(Value&& other);
Value& operator=(Value&& other);
~Value();
std::size_t Size() const;
private:
std::unique_ptr<third_party::Json> data_;
};
Taxi C++ tricks 33 / 170
Pimpl
#include <impl/json_fwd.hpp>
struct Value {
Value();
Value(Value&& other);
Value& operator=(Value&& other);
~Value();
std::size_t Size() const;
private:
std::unique_ptr<third_party::Json> data_;
};
Taxi C++ tricks 34 / 170
Pimpl
#include <formats/json.hpp>
#include <third_party/json.hpp>
Value::Value()
: data_{std::make_unique<third_party::Json>()}
{}
Value::Value(Value&& other) = default;
Value::Value& operator=(Value&& other) = default;
Value::~Value() = default;
std::size_t Value::Size() const { return data_->size(); }
Taxi C++ tricks 35 / 170
Pimpl
#include <formats/json.hpp>
#include <third_party/json.hpp>
Value::Value()
: data_{std::make_unique<third_party::Json>()}
{}
Value::Value(Value&& other) = default;
Value::Value& operator=(Value&& other) = default;
Value::~Value() = default;
std::size_t Value::Size() const { return data_->size(); }
Taxi C++ tricks 36 / 170
Pimpl
#include <formats/json.hpp>
#include <third_party/json.hpp>
Value::Value()
: data_{std::make_unique<third_party::Json>()}
{}
Value::Value(Value&& other) = default;
Value::Value& operator=(Value&& other) = default;
Value::~Value() = default;
std::size_t Value::Size() const { return data_->size(); }
Taxi C++ tricks 37 / 170
Pimpl
#include <formats/json.hpp>
#include <third_party/json.hpp>
Value::Value()
: data_{std::make_unique<third_party::Json>()}
{}
Value::Value(Value&& other) = default;
Value::Value& operator=(Value&& other) = default;
Value::~Value() = default;
std::size_t Value::Size() const { return data_->size(); }
Taxi C++ tricks 38 / 170
Pimpl
#include <formats/json.hpp>
#include <third_party/json.hpp>
Value::Value()
: data_{std::make_unique<third_party::Json>()}
{}
Value::Value(Value&& other) = default;
Value::Value& operator=(Value&& other) = default;
Value::~Value() = default;
std::size_t Value::Size() const { return data_->size(); }
Taxi C++ tricks 39 / 170
Pimpl
#include <formats/json.hpp>
#include <third_party/json.hpp>
Value::Value()
: data_{std::make_unique<third_party::Json>()} // Медленно!
{}
Value::Value(Value&& other) = default;
Value::Value& operator=(Value&& other) = default;
Value::~Value() = default;
std::size_t Value::Size() const { return data_->size(); }
Taxi C++ tricks 40 / 170
Pimpl В header file остаются только те части кода,
которые не требуют знания о полном типе.
Taxi C++ tricks 41 / 170
Pimpl В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы:
Taxi C++ tricks 42 / 170
Pimpl В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы:
●
Динамическая аллокация
Taxi C++ tricks 43 / 170
Pimpl В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы:
●
Динамическая аллокация
●
Не кеш дружелюбно
Taxi C++ tricks 44 / 170
Pimpl В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы:
●
Динамическая аллокация
●
Не кеш дружелюбно
Плюсы:
Taxi C++ tricks 45 / 170
Pimpl В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы:
●
Динамическая аллокация
●
Не кеш дружелюбно
Плюсы:
●
Не торчат наружу детали реализации
Taxi C++ tricks 46 / 170
Fast Pimpl - основы
Taxi C++ tricks
Fast Pimpl основы
struct Value {
// ...
private:
using JsonNative = third_party::Json;
std::unique_ptr<JsonNative> data_;
};
Taxi C++ tricks 48 / 170
Fast Pimpl основы
struct Value {
// ...
private:
using JsonNative = third_party::Json;
std::unique_ptr<JsonNative> data_;
};
Taxi C++ tricks 49 / 170
Fast Pimpl основы
struct Value {
// ...
private:
using JsonNative = third_party::Json;
std::aligned_storage_t<sizeof(JsonNative), alignof(JsonNative)> data_;
};
Taxi C++ tricks 50 / 170
Fast Pimpl основы
struct Value {
// ...
private:
using JsonNative = third_party::Json;
constexpr std::size_t kImplSize = 32;
constexpr std::size_t kImplAlign = 8;
std::aligned_storage_t<kImplSize, kImplAlign> data_;
};
Taxi C++ tricks 51 / 170
Fast Pimpl основы
struct Value {
// ...
private:
using JsonNative = third_party::Json;
constexpr std::size_t kImplSize = 32;
constexpr std::size_t kImplAlign = 8;
std::aligned_storage_t<kImplSize, kImplAlign> data_;
};
Taxi C++ tricks 52 / 170
Fast Pimpl основы
struct Value {
// ...
private:
using JsonNative = third_party::Json;
const JsonNative* Ptr() const noexcept;
JsonNative* Ptr() noexcept;
constexpr std::size_t kImplSize = 32;
constexpr std::size_t kImplAlign = 8;
std::aligned_storage_t<kImplSize, kImplAlign> data_;
};
Taxi C++ tricks 53 / 170
Fast Pimpl основы
Value::Value() {
new(Ptr()) JsonNative();
}
Value::~Value() {
Ptr()->~JsonNative();
}
Value::JsonNative* Value::Ptr() noexcept {
return reinterpret_cast<JsonNative*>(&data_);
}
Taxi C++ tricks 54 / 170
Fast Pimpl основы
Value::Value() {
new(Ptr()) JsonNative();
}
Value::~Value() {
Ptr()->~JsonNative();
}
Value::JsonNative* Value::Ptr() noexcept {
return reinterpret_cast<JsonNative*>(&data_);
}
Taxi C++ tricks 55 / 170
Fast Pimpl основы
Value::Value() {
new(Ptr()) JsonNative();
}
Value::~Value() {
Ptr()->~JsonNative();
}
Value::JsonNative* Value::Ptr() noexcept {
return reinterpret_cast<JsonNative*>(&data_);
}
Taxi C++ tricks 56 / 170
Fast Pimpl
(основы)
В header file остаются только те части кода,
которые не требуют знания о полном типе.
Taxi C++ tricks 57 / 170
Fast Pimpl
(основы)
В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы - неудобно пользоваться!
Taxi C++ tricks 58 / 170
Fast Pimpl
(основы)
В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы - неудобно пользоваться:
●
Нужно писать сторонню программу
Taxi C++ tricks 59 / 170
Fast Pimpl
(основы)
В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы - неудобно пользоваться:
●
Нужно писать сторонню программу
●
Следить за временем жизни
Taxi C++ tricks 60 / 170
Fast Pimpl
(основы)
В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы - неудобно пользоваться:
●
Нужно писать сторонню программу
●
Следить за временем жизни
●
reinterpret_cast
Taxi C++ tricks 61 / 170
Fast Pimpl
(основы)
В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы - неудобно пользоваться:
●
Нужно писать сторонню программу
●
Следить за временем жизни
●
reinterpret_cast
●
Приходится сильно менять cpp файл
Taxi C++ tricks 62 / 170
Fast Pimpl
(основы)
В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы - неудобно пользоваться:
●
Нужно писать сторонню программу
●
Следить за временем жизни
●
reinterpret_cast
●
Приходится сильно менять cpp файл
Плюсы:
Taxi C++ tricks 63 / 170
Fast Pimpl
(основы)
В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы - неудобно пользоваться:
●
Нужно писать сторонню программу
●
Следить за временем жизни
●
reinterpret_cast
●
Приходится сильно менять cpp файл
Плюсы:
●
Не торчат наружу детали реализации
Taxi C++ tricks 64 / 170
Fast Pimpl
(основы)
В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы - неудобно пользоваться:
●
Нужно писать сторонню программу:
●
Следить за временем жизни
●
reinterpret_cast
●
Приходится сильно менять cpp файл
Плюсы:
●
Не торчат наружу детали реализации
●
Кеш дружелюбно
Taxi C++ tricks 65 / 170
Fast Pimpl
Taxi C++ tricks
Fast Pimpl
struct Value {
// ...
private:
using JsonNative = third_party::Json;
constexpr std::size_t kImplSize = 32;
constexpr std::size_t kImplAlign = 8;
utils::FastPimpl<JsonNative, kImplSize, kImplAlign> data_;
};
Taxi C++ tricks 67 / 170
Fast Pimpl
struct Value {
// ...
private:
using JsonNative = third_party::Json;
constexpr std::size_t kImplSize = 32;
constexpr std::size_t kImplAlign = 8;
utils::FastPimpl<JsonNative, kImplSize, kImplAlign> data_;
};
Taxi C++ tricks 68 / 170
Fast Pimpl
struct Value {
// ...
private:
using JsonNative = third_party::Json;
constexpr std::size_t kImplSize = 32;
constexpr std::size_t kImplAlign = 8;
utils::FastPimpl<JsonNative, kImplSize, kImplAlign> data_;
};
Taxi C++ tricks 69 / 170
До FastPimpl
#include <formats/json.hpp>
#include <third_party/json.hpp>
Value::Value()
: data_{std::make_unique<third_party::Json>()}
{}
Value::Value(Value&& other) = default;
Value::Value& operator=(Value&& other) = default;
Value::~Value() = default;
std::size_t Value::Size() const { return data_->size(); }
Taxi C++ tricks 70 / 170
C FastPimpl
#include <formats/json.hpp>
#include <third_party/json.hpp>
Value::Value() = default;
Value::Value(Value&& other) = default;
Value::Value& operator=(Value&& other) = default;
Value::~Value() = default;
std::size_t Value::Size() const { return data_->size(); }
Taxi C++ tricks 71 / 170
Fast Pimpl имплементация
Taxi C++ tricks
FastPimpl имплементация
template <class T, size_t Size, size_t Alignment>
class FastPimpl {
public:
template <class... Args>
explicit FastPimpl(Args&&... args) {
new (Ptr()) T(std::forward<Args>(args)...);
}
FastPimpl& operator=(FastPimpl&& rhs) {
*Ptr() = std::move(*rhs);
return *this;
}
Taxi C++ tricks 73 / 170
FastPimpl имплементация
template <class T, size_t Size, size_t Alignment>
class FastPimpl {
public:
template <class... Args>
explicit FastPimpl(Args&&... args) {
new (Ptr()) T(std::forward<Args>(args)...);
}
FastPimpl& operator=(FastPimpl&& rhs) {
*Ptr() = std::move(*rhs);
return *this;
}
Taxi C++ tricks 74 / 170
FastPimpl имплементация
template <class T, size_t Size, size_t Alignment>
class FastPimpl {
public:
template <class... Args>
explicit FastPimpl(Args&&... args) {
new (Ptr()) T(std::forward<Args>(args)...);
}
FastPimpl& operator=(FastPimpl&& rhs) {
*Ptr() = std::move(*rhs);
return *this;
}
Taxi C++ tricks 75 / 170
FastPimpl имплементация
template <class T, size_t Size, size_t Alignment>
class FastPimpl {
public:
template <class... Args>
explicit FastPimpl(Args&&... args) {
new (Ptr()) T(std::forward<Args>(args)...);
}
FastPimpl& operator=(FastPimpl&& rhs) {
*Ptr() = std::move(*rhs);
return *this;
}
Taxi C++ tricks 76 / 170
FastPimpl имплементация
T* operator->() noexcept { return Ptr(); }
const T* operator->() const noexcept { return Ptr(); }
T& operator*() noexcept { return *Ptr(); }
const T& operator*() const noexcept { return *Ptr(); }
Taxi C++ tricks 77 / 170
FastPimpl имплементация
~FastPimpl() noexcept {
validate<sizeof(T), alignof(T)>();
Ptr()->~T();
}
Taxi C++ tricks 78 / 170
FastPimpl имплементация
~FastPimpl() noexcept {
validate<sizeof(T), alignof(T)>();
Ptr()->~T();
}
Taxi C++ tricks 79 / 170
FastPimpl имплементация
template <class T, size_t Size, size_t Alignment>
class FastPimpl {
// ...
private:
template <std::size_t ActualSize, std::size_t ActualAlignment>
static void validate() noexcept {
static_assert(Size == ActualSize, "Size and sizeof(T) mismatch");
static_assert(Alignment == ActualAlignment, "Alignment and alignof(T) mismatch");
}
Taxi C++ tricks 80 / 170
FastPimpl имплементация
template <class T, size_t Size, size_t Alignment>
class FastPimpl {
// ...
private:
template <std::size_t ActualSize, std::size_t ActualAlignment>
static void validate() noexcept {
static_assert(Size == ActualSize, "Size and sizeof(T) mismatch");
static_assert(Alignment == ActualAlignment, "Alignment and alignof(T) mismatch");
}
Taxi C++ tricks 81 / 170
FastPimpl имплементация
template <class T, size_t Size, size_t Alignment>
class FastPimpl {
// ...
private:
template <std::size_t ActualSize, std::size_t ActualAlignment>
static void validate() noexcept {
static_assert(Size == ActualSize, "Size and sizeof(T) mismatch");
static_assert(Alignment == ActualAlignment, "Alignment and alignof(T) mismatch");
}
Taxi C++ tricks 82 / 170
FastPimpl имплементация
<source>: In instantiation of 'void FastPimpl<T, Size, Alignment>::validate() [with int
ActualSize = 32; int ActualAlignment = 8; T = std::string; int Size = 8; int Alignment =
8]'
Taxi C++ tricks 83 / 170
Fast Pimpl В header file остаются только те части кода,
которые не требуют знания о полном типе.
Taxi C++ tricks 84 / 170
Fast Pimpl В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы:
Taxi C++ tricks 85 / 170
Fast Pimpl В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы:
●
Нужно написать 2 константы
Taxi C++ tricks 86 / 170
Fast Pimpl В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы:
●
Нужно написать 2 константы
Плюсы:
Taxi C++ tricks 87 / 170
Fast Pimpl В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы:
●
Нужно написать 2 константы
Плюсы:
●
Не торчат наружу детали реализации
Taxi C++ tricks 88 / 170
Fast Pimpl В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы:
●
Нужно написать 2 константы
Плюсы:
●
Не торчат наружу детали реализации
●
Кеш дружелюбно
Taxi C++ tricks 89 / 170
Fast Pimpl В header file остаются только те части кода,
которые не требуют знания о полном типе.
Минусы:
●
Нужно написать 2 константы
Плюсы:
●
Не торчат наружу детали реализации
●
Кеш дружелюбно
●
Минимум изменений в cpp файле
Taxi C++ tricks 90 / 170
Логирование
Taxi C++ tricks
Логирование
Taxi C++ tricks 92 / 170
Логирование
#include <iostream>
std::cerr << "Log message";
Taxi C++ tricks 93 / 170
Логирование
#include <iostream>
std::cerr << timestamp() << "Log message";
Taxi C++ tricks 94 / 170
Логирование
#include <iostream>
std::osyncstream{std::cerr} << timestamp() << "Log message";
Taxi C++ tricks 95 / 170
Логирование
struct LogHelper {
LogHelper() { oss << timestamp(); }
~LogHelper() { std::cerr << oss.str(); }
private:
std::ostringstream oss;
};
template <class T>
LogHelper& operator<<(LogHelper& lh, const T& value) {
lh.oss << value;
return lh;
}
Taxi C++ tricks 96 / 170
Логирование
struct LogHelper {
LogHelper() { oss << timestamp(); }
~LogHelper() { std::cerr << oss.str(); }
private:
std::ostringstream oss;
};
template <class T>
LogHelper& operator<<(LogHelper& lh, const T& value) {
lh.oss << value;
return lh;
}
Taxi C++ tricks 97 / 170
Логирование
struct LogHelper {
LogHelper() { oss << timestamp(); }
~LogHelper() { std::cerr << oss.str(); }
private:
std::ostringstream oss;
};
template <class T>
LogHelper& operator<<(LogHelper& lh, const T& value) {
lh.oss << value;
return lh;
}
Taxi C++ tricks 98 / 170
Логирование
struct LogHelper {
LogHelper() { oss << timestamp(); }
~LogHelper() { std::cerr << oss.str(); }
private:
std::ostringstream oss;
};
template <class T>
LogHelper& operator<<(LogHelper& lh, const T& value) {
lh.oss << value;
return lh;
}
Taxi C++ tricks 99 / 170
Логирование
struct LogHelper {
LogHelper() { oss << timestamp(); }
~LogHelper() { std::cerr << oss.str(); }
private:
std::ostringstream oss; // Очень-очень медленно!
};
template <class T>
LogHelper& operator<<(LogHelper& lh, const T& value) {
lh.oss << value;
return lh;
}
Taxi C++ tricks 100 / 170
Логирование (было)
private:
std::ostringstream oss;
};
Taxi C++ tricks 101 / 170
Логирование (стало)
private:
FastStackBuffer buffer_;
struct LazyInitedStream;
std::optional<LazyInitedStream> lazy_;
};
Taxi C++ tricks 102 / 170
Логирование (стало)
private:
FastStackBuffer buffer_; // буффер использующий стек через std::array<char, 1024>
struct LazyInitedStream;
std::optional<LazyInitedStream> lazy_;
};
Taxi C++ tricks 103 / 170
Логирование (стало)
private:
FastStackBuffer buffer_; // буффер использующий стек через std::array<char, 1024>
struct LazyInitedStream; // содержит std::ostream
std::optional<LazyInitedStream> lazy_;
};
Taxi C++ tricks 104 / 170
Логирование (стало)
private:
FastStackBuffer buffer_; // буффер использующий стек через std::array<char, 1024>
struct LazyInitedStream; // содержит std::ostream
std::optional<LazyInitedStream> lazy_; // по умолчанию ничего не конструирует
};
Taxi C++ tricks 105 / 170
Логирование (было)
template <class T>
LogHelper& operator<<(LogHelper& lh, const T& value) {
lh.oss << value;
return lh;
}
Taxi C++ tricks 106 / 170
Логирование (стало)
template <typename T>
LogHelper& LogHelper::operator<<(const T& value) {
if constexpr (std::is_constructible<utils::string_view, T>::value) {
buffer_.Put(value);
} else if constexpr (std::is_base_of<std::exception, T>::value) {
buffer_.PutException(value);
} else {
Stream() << value;
}
return *this;
}
Taxi C++ tricks 107 / 170
Логирование (стало)
template <typename T>
LogHelper& LogHelper::operator<<(const T& value) {
if constexpr (std::is_constructible<utils::string_view, T>::value) {
buffer_.Put(value);
} else if constexpr (std::is_base_of<std::exception, T>::value) {
buffer_.PutException(value);
} else {
Stream() << value;
}
return *this;
}
Taxi C++ tricks 108 / 170
Логирование (стало)
template <typename T>
LogHelper& LogHelper::operator<<(const T& value) {
if constexpr (std::is_constructible<utils::string_view, T>::value) {
buffer_.Put(value);
} else if constexpr (std::is_base_of<std::exception, T>::value) {
buffer_.PutException(value);
} else {
Stream() << value;
}
return *this;
}
Taxi C++ tricks 109 / 170
Логирование (стало)
template <typename T>
LogHelper& LogHelper::operator<<(const T& value) {
if constexpr (std::is_constructible<utils::string_view, T>::value) {
buffer_.Put(value);
} else if constexpr (std::is_base_of<std::exception, T>::value) {
buffer_.PutException(value);
} else {
Stream() << value;
}
return *this;
}
Taxi C++ tricks 110 / 170
Логирование (стало)
private:
FastStackBuffer buffer_; // буффер использующий стек через std::array<char, 1024>
struct LazyInitedStream; // содержит std::ostream
std::optional<LazyInitedStream> lazy_; // по умолчанию ничего не конструирует
};
Taxi C++ tricks 111 / 170
Логирование
private:
FastStackBuffer buffer_;
struct LazyInitedStream {
BufferStd sbuf;
std::ostream ostr;
explicit LazyInitedStream(FastStackBuffer& impl) : sbuf{impl}, ostr(&sbuf) {}
};
std::optional<LazyInitedStream> lazy_;
};
Taxi C++ tricks 112 / 170
Логирование
private:
FastStackBuffer buffer_;
struct LazyInitedStream {
BufferStd sbuf;
std::ostream ostr;
explicit LazyInitedStream(FastStackBuffer& impl) : sbuf{impl}, ostr(&sbuf) {}
};
std::optional<LazyInitedStream> lazy_;
};
Taxi C++ tricks 113 / 170
Логирование
struct BufferStd final : public std::streambuf {
explicit BufferStd(FastStackBuffer& impl) : impl_{impl} {}
private:
int_type overflow(int_type c) override;
std::streamsize xsputn(const char_type* s, std::streamsize n) override;
FastStackBuffer& impl_;
};
Taxi C++ tricks 114 / 170
Логирование
struct BufferStd final : public std::streambuf {
explicit BufferStd(FastStackBuffer& impl) : impl_{impl} {}
private:
int_type overflow(int_type c) override;
std::streamsize xsputn(const char_type* s, std::streamsize n) override;
FastStackBuffer& impl_;
};
Taxi C++ tricks 115 / 170
Логирование
struct BufferStd final : public std::streambuf {
explicit BufferStd(FastStackBuffer& impl) : impl_{impl} {}
private:
int_type overflow(int_type c) override;
std::streamsize xsputn(const char_type* s, std::streamsize n) override;
FastStackBuffer& impl_;
};
Taxi C++ tricks 116 / 170
Логирование
struct BufferStd final : public std::streambuf {
explicit BufferStd(FastStackBuffer& impl) : impl_{impl} {}
private:
int_type overflow(int_type c) override;
std::streamsize xsputn(const char_type* s, std::streamsize n) override;
FastStackBuffer& impl_;
};
Taxi C++ tricks 117 / 170
Логирование
private:
FastStackBuffer buffer_;
std::optional<LazyInitedStream> lazy_;
std::ostream& Stream() {
if (!lazy_) {
lazy_.emplace(buffer_);
}
return lazy_->ostr;
}
};
Taxi C++ tricks 118 / 170
Логирование
private:
FastStackBuffer buffer_;
std::optional<LazyInitedStream> lazy_;
std::ostream& Stream() {
if (!lazy_) {
lazy_.emplace(buffer_);
}
return lazy_->ostr;
}
};
Taxi C++ tricks 119 / 170
Логирование
std::ostream& operator<<(std::ostream& os, const models::DriverInfo& info) {
return os << "Id = " << info.id << ", name = " << info.name;
}
Taxi C++ tricks 120 / 170
Логирование
std::ostream& operator<<(std::ostream& os, const models::DriverInfo& info) {
return os << "Id = " << info.id << ", name = " << info.name;
}
LogHelper& operator<<(LogHelper& lh, const models::DriverInfo& info) {
return lh << "Id = " << info.id << ", name = " << info.name;
}
Taxi C++ tricks 121 / 170
Логирование
LogHelper& operator<<(LogHelper& lh, const models::DriverInfo& info) {
return lh << "Id = " << info.id << ", name = " << info.name;
}
Taxi C++ tricks 122 / 170
Логирование (бенчмарки)
Было | Стало
-------------------------------------
LogNumber<int> 682 ns | 321 ns
LogNumber<long> 680 ns | 318 ns
LogChar/8 690 ns | 334 ns
LogChar/16 718 ns | 419 ns
LogChar/512 2066 ns | 1928 ns
LogStruct 812 ns | 685 ns
Taxi C++ tricks 123 / 170
Note: в бенчмарках LogHelper() так же
пишет уровень логирования, время, id
корутины, id потока, id соединения;
~LogHelper() честно отрабатывает и
отсылает данные в аналог std::cerr.
Несмотря на эти «неоптимизируемые
расходы», мы получаем прирост
производительности в ~2 раза.
Логирование (маленькая хитрость)
Id id{42};
LogHelper lh{kDebug};
lh << staktrace() << id << ':' << db.FetchUserById(id);
Taxi C++ tricks 124 / 170
Логирование (маленькая хитрость)
Id id{42};
LOG_DEBUG() << staktrace() << id << ':' << db.FetchUserById(id);
Taxi C++ tricks 125 / 170
Логирование (маленькая хитрость)
#define LOG_DEBUG() 
if (kDebug >= CurrentLogLevel()) LogHelper{}.AsLValue()
Taxi C++ tricks 126 / 170
Логирование
Taxi C++ tricks 127 / 170
Логирование Плюсы:
Taxi C++ tricks 128 / 170
Логирование Плюсы:
●
Нет динамических аллокаций
Taxi C++ tricks 129 / 170
Логирование Плюсы:
●
Нет динамических аллокаций
●
Быстрое форматирование без std::locale
Taxi C++ tricks 130 / 170
Логирование Плюсы:
●
Нет динамических аллокаций
●
Быстрое форматирование без std::locale
●
Переключение на рантайме уровня
логирования
Taxi C++ tricks 131 / 170
Логирование Плюсы:
●
Нет динамических аллокаций
●
Быстрое форматирование без std::locale
●
Переключение на рантайме уровня
логирования
●
Не вычисляем лишнего
Taxi C++ tricks 132 / 170
Parse
Taxi C++ tricks
Parse
auto inf = json.As<models::DriverInfo>();
Taxi C++ tricks 134 / 170
Parse
auto inf = json.As<models::DriverInfo>();
auto inf = yaml.As<models::DriverInfo>();
Taxi C++ tricks 135 / 170
Parse
auto inf = json.As<models::DriverInfo>();
auto inf = yaml.As<models::DriverInfo>();
auto inf = bson.As<models::DriverInfo>();
Taxi C++ tricks 136 / 170
Parse – точка кастомизации, которая должна искать в:
Taxi C++ tricks 137 / 170
Parse – точка кастомизации, которая должна искать в:
●
namespce T
Taxi C++ tricks 138 / 170
Parse – точка кастомизации, которая должна искать в:
●
namespce T
●
где-то, где описаны общие парсеры
Taxi C++ tricks 139 / 170
Parse – точка кастомизации, которая должна искать в:
●
namespce T
●
где-то, где описаны общие парсеры
●
где-то, где описаны формато-специфичные
парсеры
Taxi C++ tricks 140 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
return Parse(*this); // ???
}
};
} // namespace formats::json
Taxi C++ tricks 141 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
return Parse(*this); // ???
}
};
} // namespace formats::json
Taxi C++ tricks 142 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
return T::Parse(*this);
}
};
} // namespace formats::json
Taxi C++ tricks 143 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
return T::Parse(*this); // std::vector<DriverInfo>, boost::optional<DriverInfo> :(
}
};
} // namespace formats::json
Taxi C++ tricks 144 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
return Parse<T>(*this);
}
};
} // namespace formats::json
Taxi C++ tricks 145 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
return Parse<T>(*this); // std::vector<DriverInfo>, boost::optional<DriverInfo> :(
}
};
} // namespace formats::json
Taxi C++ tricks 146 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
T value;
Parse(*this, value);
return value;
}
};
} // namespace formats::json
Taxi C++ tricks 147 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
T value; // не default constructible типы?
Parse(*this, value);
return value;
}
};
} // namespace formats::json
Taxi C++ tricks 148 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
T* value = nullptr;
return Parse(*this, value);
}
};
} // namespace formats::json
Taxi C++ tricks 149 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
T* value = nullptr; // Отстрел ноги :(
return Parse(*this, value);
}
};
} // namespace formats::json
Taxi C++ tricks 150 / 170
Parse — что делать?
Taxi C++ tricks
Parse
#pragma once
namespace formats::parse {
template <class T>
struct To {};
} // namespace formats::parse
Taxi C++ tricks 152 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
return Parse(*this, parse::To<T>{});
}
};
} // namespace formats::json
Taxi C++ tricks 153 / 170
ADL
Taxi C++ tricks 154 / 170
ADL Ищет функции с заданными именем в
●
namespace аргументов функции
Taxi C++ tricks 155 / 170
ADL Ищет функции с заданными именем в
●
namespace аргументов функции
●
и namespace шаблонов аргументов функций
Taxi C++ tricks 156 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
return Parse(*this, parse::To<T>{});
}
};
} // namespace formats::json
Taxi C++ tricks 157 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
return Parse(*this, parse::To<T>{}); // namespace formats::<json>
}
};
} // namespace formats::json
Taxi C++ tricks 158 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
return Parse(*this, parse::To<T>{}); // namespace formats::parse
}
};
} // namespace formats::json
Taxi C++ tricks 159 / 170
Parse
namespace formats::json {
struct Value {
template <class T>
T As() {
return Parse(*this, parse::To<T>{}); // namespace of T
}
};
} // namespace formats::json
Taxi C++ tricks 160 / 170
Parse
namespace formats::parse {
template <class Value, typename T>
auto Parse(const Value& value, To<std::unordered_map<std::string, T>>);
} // namespace formats::parse
Taxi C++ tricks 161 / 170
Parse
namespace drivers::models {
template <class Value>
auto Parse(const Value& v, formats::parse::To<DriverInfo>);
} // namespace drivers::models
Taxi C++ tricks 162 / 170
Parse
namespace formats::bson {
auto Parse(const bson::Value& v, parse::To<std::chrono::system_clock::time_point>);
} // namespace formats::bson
Taxi C++ tricks 163 / 170
Parse
Taxi C++ tricks 164 / 170
Parse Плюсы
Taxi C++ tricks 165 / 170
Parse Плюсы:
●
Одна функция на все форматы
Taxi C++ tricks 166 / 170
Parse Плюсы:
●
Одна функция на все форматы
●
Можно писать парсеры в своём namepsace
Taxi C++ tricks 167 / 170
Parse Плюсы:
●
Одна функция на все форматы
●
Можно писать парсеры в своём namepsace
●
Нет мороки с linker или порядком заголовков
Taxi C++ tricks 168 / 170
Спасибо
Полухин Антон
Эксперт-разработчик C++
antoshkka@yandex-team.ru
antoshkka@gmail.com
https://github.com/apolukhin
https://stdcpp.ru/

More Related Content

Similar to C++ трюки из Такси. Антон Полухин ➠ CoreHard Autumn 2019

Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...Yandex
 
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)Ontico
 
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++Pavel Tsukanov
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Yandex
 
Tdd and BDD
Tdd and BDDTdd and BDD
Tdd and BDDAcceptic
 
Cтатический анализ кода (на примере DDD-фреймворка)
Cтатический анализ кода (на примере DDD-фреймворка)Cтатический анализ кода (на примере DDD-фреймворка)
Cтатический анализ кода (на примере DDD-фреймворка)ngrebnev
 
C++ tema 1
C++ tema 1C++ tema 1
C++ tema 1krisT7
 
презентации продолжение банкета
презентации продолжение банкетапрезентации продолжение банкета
презентации продолжение банкетаstudent_kai
 
Tarantool Modules, Tarantool Meetup 2016-08-25
Tarantool Modules, Tarantool Meetup 2016-08-25Tarantool Modules, Tarantool Meetup 2016-08-25
Tarantool Modules, Tarantool Meetup 2016-08-25Roman Tsisyk
 
Cpp0x Introduction
Cpp0x IntroductionCpp0x Introduction
Cpp0x IntroductionFedor Vompe
 
Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Yauheni Akhotnikau
 
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...corehard_by
 
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Fwdays
 
Парсим и кодогенерируем для С++ с использованием clang
Парсим и кодогенерируем для С++ с использованием clangПарсим и кодогенерируем для С++ с использованием clang
Парсим и кодогенерируем для С++ с использованием clangcorehard_by
 
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...OdessaFrontend
 
DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыPlatonov Sergey
 
Статический анализ Си++ кода
Статический анализ Си++ кодаСтатический анализ Си++ кода
Статический анализ Си++ кодаTatyanazaxarova
 

Similar to C++ трюки из Такси. Антон Полухин ➠ CoreHard Autumn 2019 (20)

Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
 
лекция 1
лекция 1лекция 1
лекция 1
 
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
 
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
 
лекция 2
лекция 2лекция 2
лекция 2
 
Tdd and BDD
Tdd and BDDTdd and BDD
Tdd and BDD
 
Cтатический анализ кода (на примере DDD-фреймворка)
Cтатический анализ кода (на примере DDD-фреймворка)Cтатический анализ кода (на примере DDD-фреймворка)
Cтатический анализ кода (на примере DDD-фреймворка)
 
C++ tema 1
C++ tema 1C++ tema 1
C++ tema 1
 
презентации продолжение банкета
презентации продолжение банкетапрезентации продолжение банкета
презентации продолжение банкета
 
Tarantool Modules, Tarantool Meetup 2016-08-25
Tarantool Modules, Tarantool Meetup 2016-08-25Tarantool Modules, Tarantool Meetup 2016-08-25
Tarantool Modules, Tarantool Meetup 2016-08-25
 
Cpp0x Introduction
Cpp0x IntroductionCpp0x Introduction
Cpp0x Introduction
 
Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?
 
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
 
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
 
Парсим и кодогенерируем для С++ с использованием clang
Парсим и кодогенерируем для С++ с использованием clangПарсим и кодогенерируем для С++ с использованием clang
Парсим и кодогенерируем для С++ с использованием clang
 
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
 
DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансы
 
Lektsia 9
Lektsia 9Lektsia 9
Lektsia 9
 
Статический анализ Си++ кода
Статический анализ Си++ кодаСтатический анализ Си++ кода
Статический анализ Си++ кода
 

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 Autumn 2019

  • 1.
  • 5. userver – framework для написания высокопроизводительных приложений Taxi C++ tricks 5 / 170
  • 6. userver – framework для написания высокопроизводительных приложений Прост и удобен в использовании Taxi C++ tricks 6 / 170
  • 7. userver – framework для написания высокопроизводительных приложений Прост и удобен в использовании: – Работа с форматами JSON/BSON/Yaml/… Taxi C++ tricks 7 / 170
  • 8. userver – framework для написания высокопроизводительных приложений Прост и удобен в использовании: – Работа с форматами JSON/BSON/Yaml/… – Логирование Taxi C++ tricks 8 / 170
  • 9. userver – framework для написания высокопроизводительных приложений Прост и удобен в использовании: – Работа с форматами JSON/BSON/Yaml/… – Логирование – Сеть Taxi C++ tricks 9 / 170
  • 10. userver – framework для написания высокопроизводительных приложений Прост и удобен в использовании: – Работа с форматами JSON/BSON/Yaml/… – Логирование – Сеть – Драйвера Postgres/Mongo/… Taxi C++ tricks 10 / 170
  • 11. userver – framework для написания высокопроизводительных приложений Прост и удобен в использовании: – Работа с форматами JSON/BSON/Yaml/… – Логирование – Сеть – Драйвера Postgres/Mongo/… – Корутины Taxi C++ tricks 11 / 170
  • 12. userver – framework для написания высокопроизводительных приложений Прост и удобен в использовании: – Работа с форматами JSON/BSON/Yaml/… – Логирование – Сеть – Драйвера Postgres/Mongo/… – Корутины – Кодогенерация Taxi C++ tricks 12 / 170
  • 13. userver – framework для написания высокопроизводительных приложений Прост и удобен в использовании: – Работа с форматами JSON/BSON/Yaml/… – Логирование – Сеть – Драйвера Postgres/Mongo/… – Корутины – Кодогенерация – … Taxi C++ tricks 13 / 170
  • 14. userver – framework для написания высокопроизводительных приложений Прост и удобен в использовании: – Работа с форматами JSON/BSON/Yaml/… – Логирование – Сеть – Драйвера Postgres/Mongo/… – Корутины – Кодогенерация – … Очень-очень быстрый! Taxi C++ tricks 14 / 170
  • 15. userver – framework для написания высокопроизводительных приложений Прост и удобен в использовании: – Работа с форматами JSON/BSON/Yaml/… – Логирование – Сеть – Драйвера Postgres/Mongo/… – Корутины – Кодогенерация – … Очень-очень быстрый! Taxi C++ tricks 15 / 170
  • 17. userver Очень-очень быстрый! Зачастую привычные решения нам не подходят Taxi C++ tricks 17 / 170
  • 19. Pimpl #include <third_party/json.hpp> namespace formats::json { class Exception; struct Value; } // namespace formats::json Taxi C++ tricks 19 / 170
  • 20. Pimpl #include <third_party/json.hpp> struct Value { Value() = default; Value(Value&& other) = default; Value& operator=(Value&& other) = default; ~Value() = default; std::size_t Size() const { return data_.size(); } private: third_party::Json data_; }; Taxi C++ tricks 20 / 170
  • 21. Pimpl #include <third_party/json.hpp> struct Value { Value() = default; Value(Value&& other) = default; Value& operator=(Value&& other) = default; ~Value() = default; std::size_t Size() const { return data_.size(); } private: third_party::Json data_; }; Taxi C++ tricks 21 / 170
  • 22. Pimpl #include <third_party/json.hpp> struct Value { Value() = default; Value(Value&& other) = default; Value& operator=(Value&& other) = default; ~Value() = default; std::size_t Size() const { return data_.size(); } private: third_party::Json data_; }; Taxi C++ tricks 22 / 170
  • 23. Pimpl #include <third_party/json.hpp> // PROBLEMS! struct Value { Value() = default; Value(Value&& other) = default; Value& operator=(Value&& other) = default; ~Value() = default; std::size_t Size() const { return data_.size(); } private: third_party::Json data_; }; Taxi C++ tricks 23 / 170
  • 24. Pimpl std::size_t Sample(const formats::json::Value& value) { try { return value.Size(); } catch (const third_party::Exception& e) { LOG_ERROR() << e; return kFallback; } } Taxi C++ tricks 24 / 170
  • 25. Pimpl std::size_t Sample(const formats::json::Value& value) { try { return value.Size(); } catch (const third_party::Exception& e) { LOG_ERROR() << e; return kFallback; } } Taxi C++ tricks 25 / 170
  • 26. Pimpl #include <third_party/json.hpp> namespace formats::json { class Exception; struct Value; } // namespace formats::json Taxi C++ tricks 26 / 170
  • 27. Pimpl namespace third_party { struct Json; // forward declaration } // namespace third_party namespace formats::json { class Exception; struct Value; } // namespace formats::json Taxi C++ tricks 27 / 170
  • 28. Pimpl #include <impl/json_fwd.hpp> struct Value { Value() = default; Value(Value&& other) = default; Value& operator=(Value&& other) = default; ~Value() = default; std::size_t Size() const { return data_.size(); } private: third_party::Json data_; }; Taxi C++ tricks 28 / 170
  • 29. Pimpl #include <impl/json_fwd.hpp> struct Value { Value() = default; Value(Value&& other) = default; Value& operator=(Value&& other) = default; ~Value() = default; std::size_t Size() const { return data_.size(); } private: third_party::Json data_; }; Taxi C++ tricks 29 / 170
  • 30. Pimpl #include <impl/json_fwd.hpp> struct Value { Value() = default; Value(Value&& other) = default; Value& operator=(Value&& other) = default; ~Value() = default; std::size_t Size() const { return data_.size(); } private: third_party::Json data_; }; Taxi C++ tricks 30 / 170
  • 31. Pimpl error: field 'data_' has incomplete type 'third_party::Json' | third_party::Json data_; Taxi C++ tricks 31 / 170
  • 32. Pimpl #include <impl/json_fwd.hpp> struct Value { Value() = default; Value(Value&& other) = default; Value& operator=(Value&& other) = default; ~Value() = default; std::size_t Size() const { return data_.size(); } private: third_party::Json data_; }; Taxi C++ tricks 32 / 170
  • 33. Pimpl #include <impl/json_fwd.hpp> struct Value { Value(); Value(Value&& other); Value& operator=(Value&& other); ~Value(); std::size_t Size() const; private: std::unique_ptr<third_party::Json> data_; }; Taxi C++ tricks 33 / 170
  • 34. Pimpl #include <impl/json_fwd.hpp> struct Value { Value(); Value(Value&& other); Value& operator=(Value&& other); ~Value(); std::size_t Size() const; private: std::unique_ptr<third_party::Json> data_; }; Taxi C++ tricks 34 / 170
  • 35. Pimpl #include <formats/json.hpp> #include <third_party/json.hpp> Value::Value() : data_{std::make_unique<third_party::Json>()} {} Value::Value(Value&& other) = default; Value::Value& operator=(Value&& other) = default; Value::~Value() = default; std::size_t Value::Size() const { return data_->size(); } Taxi C++ tricks 35 / 170
  • 36. Pimpl #include <formats/json.hpp> #include <third_party/json.hpp> Value::Value() : data_{std::make_unique<third_party::Json>()} {} Value::Value(Value&& other) = default; Value::Value& operator=(Value&& other) = default; Value::~Value() = default; std::size_t Value::Size() const { return data_->size(); } Taxi C++ tricks 36 / 170
  • 37. Pimpl #include <formats/json.hpp> #include <third_party/json.hpp> Value::Value() : data_{std::make_unique<third_party::Json>()} {} Value::Value(Value&& other) = default; Value::Value& operator=(Value&& other) = default; Value::~Value() = default; std::size_t Value::Size() const { return data_->size(); } Taxi C++ tricks 37 / 170
  • 38. Pimpl #include <formats/json.hpp> #include <third_party/json.hpp> Value::Value() : data_{std::make_unique<third_party::Json>()} {} Value::Value(Value&& other) = default; Value::Value& operator=(Value&& other) = default; Value::~Value() = default; std::size_t Value::Size() const { return data_->size(); } Taxi C++ tricks 38 / 170
  • 39. Pimpl #include <formats/json.hpp> #include <third_party/json.hpp> Value::Value() : data_{std::make_unique<third_party::Json>()} {} Value::Value(Value&& other) = default; Value::Value& operator=(Value&& other) = default; Value::~Value() = default; std::size_t Value::Size() const { return data_->size(); } Taxi C++ tricks 39 / 170
  • 40. Pimpl #include <formats/json.hpp> #include <third_party/json.hpp> Value::Value() : data_{std::make_unique<third_party::Json>()} // Медленно! {} Value::Value(Value&& other) = default; Value::Value& operator=(Value&& other) = default; Value::~Value() = default; std::size_t Value::Size() const { return data_->size(); } Taxi C++ tricks 40 / 170
  • 41. Pimpl В header file остаются только те части кода, которые не требуют знания о полном типе. Taxi C++ tricks 41 / 170
  • 42. Pimpl В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы: Taxi C++ tricks 42 / 170
  • 43. Pimpl В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы: ● Динамическая аллокация Taxi C++ tricks 43 / 170
  • 44. Pimpl В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы: ● Динамическая аллокация ● Не кеш дружелюбно Taxi C++ tricks 44 / 170
  • 45. Pimpl В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы: ● Динамическая аллокация ● Не кеш дружелюбно Плюсы: Taxi C++ tricks 45 / 170
  • 46. Pimpl В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы: ● Динамическая аллокация ● Не кеш дружелюбно Плюсы: ● Не торчат наружу детали реализации Taxi C++ tricks 46 / 170
  • 47. Fast Pimpl - основы Taxi C++ tricks
  • 48. Fast Pimpl основы struct Value { // ... private: using JsonNative = third_party::Json; std::unique_ptr<JsonNative> data_; }; Taxi C++ tricks 48 / 170
  • 49. Fast Pimpl основы struct Value { // ... private: using JsonNative = third_party::Json; std::unique_ptr<JsonNative> data_; }; Taxi C++ tricks 49 / 170
  • 50. Fast Pimpl основы struct Value { // ... private: using JsonNative = third_party::Json; std::aligned_storage_t<sizeof(JsonNative), alignof(JsonNative)> data_; }; Taxi C++ tricks 50 / 170
  • 51. Fast Pimpl основы struct Value { // ... private: using JsonNative = third_party::Json; constexpr std::size_t kImplSize = 32; constexpr std::size_t kImplAlign = 8; std::aligned_storage_t<kImplSize, kImplAlign> data_; }; Taxi C++ tricks 51 / 170
  • 52. Fast Pimpl основы struct Value { // ... private: using JsonNative = third_party::Json; constexpr std::size_t kImplSize = 32; constexpr std::size_t kImplAlign = 8; std::aligned_storage_t<kImplSize, kImplAlign> data_; }; Taxi C++ tricks 52 / 170
  • 53. Fast Pimpl основы struct Value { // ... private: using JsonNative = third_party::Json; const JsonNative* Ptr() const noexcept; JsonNative* Ptr() noexcept; constexpr std::size_t kImplSize = 32; constexpr std::size_t kImplAlign = 8; std::aligned_storage_t<kImplSize, kImplAlign> data_; }; Taxi C++ tricks 53 / 170
  • 54. Fast Pimpl основы Value::Value() { new(Ptr()) JsonNative(); } Value::~Value() { Ptr()->~JsonNative(); } Value::JsonNative* Value::Ptr() noexcept { return reinterpret_cast<JsonNative*>(&data_); } Taxi C++ tricks 54 / 170
  • 55. Fast Pimpl основы Value::Value() { new(Ptr()) JsonNative(); } Value::~Value() { Ptr()->~JsonNative(); } Value::JsonNative* Value::Ptr() noexcept { return reinterpret_cast<JsonNative*>(&data_); } Taxi C++ tricks 55 / 170
  • 56. Fast Pimpl основы Value::Value() { new(Ptr()) JsonNative(); } Value::~Value() { Ptr()->~JsonNative(); } Value::JsonNative* Value::Ptr() noexcept { return reinterpret_cast<JsonNative*>(&data_); } Taxi C++ tricks 56 / 170
  • 57. Fast Pimpl (основы) В header file остаются только те части кода, которые не требуют знания о полном типе. Taxi C++ tricks 57 / 170
  • 58. Fast Pimpl (основы) В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы - неудобно пользоваться! Taxi C++ tricks 58 / 170
  • 59. Fast Pimpl (основы) В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы - неудобно пользоваться: ● Нужно писать сторонню программу Taxi C++ tricks 59 / 170
  • 60. Fast Pimpl (основы) В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы - неудобно пользоваться: ● Нужно писать сторонню программу ● Следить за временем жизни Taxi C++ tricks 60 / 170
  • 61. Fast Pimpl (основы) В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы - неудобно пользоваться: ● Нужно писать сторонню программу ● Следить за временем жизни ● reinterpret_cast Taxi C++ tricks 61 / 170
  • 62. Fast Pimpl (основы) В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы - неудобно пользоваться: ● Нужно писать сторонню программу ● Следить за временем жизни ● reinterpret_cast ● Приходится сильно менять cpp файл Taxi C++ tricks 62 / 170
  • 63. Fast Pimpl (основы) В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы - неудобно пользоваться: ● Нужно писать сторонню программу ● Следить за временем жизни ● reinterpret_cast ● Приходится сильно менять cpp файл Плюсы: Taxi C++ tricks 63 / 170
  • 64. Fast Pimpl (основы) В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы - неудобно пользоваться: ● Нужно писать сторонню программу ● Следить за временем жизни ● reinterpret_cast ● Приходится сильно менять cpp файл Плюсы: ● Не торчат наружу детали реализации Taxi C++ tricks 64 / 170
  • 65. Fast Pimpl (основы) В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы - неудобно пользоваться: ● Нужно писать сторонню программу: ● Следить за временем жизни ● reinterpret_cast ● Приходится сильно менять cpp файл Плюсы: ● Не торчат наружу детали реализации ● Кеш дружелюбно Taxi C++ tricks 65 / 170
  • 67. Fast Pimpl struct Value { // ... private: using JsonNative = third_party::Json; constexpr std::size_t kImplSize = 32; constexpr std::size_t kImplAlign = 8; utils::FastPimpl<JsonNative, kImplSize, kImplAlign> data_; }; Taxi C++ tricks 67 / 170
  • 68. Fast Pimpl struct Value { // ... private: using JsonNative = third_party::Json; constexpr std::size_t kImplSize = 32; constexpr std::size_t kImplAlign = 8; utils::FastPimpl<JsonNative, kImplSize, kImplAlign> data_; }; Taxi C++ tricks 68 / 170
  • 69. Fast Pimpl struct Value { // ... private: using JsonNative = third_party::Json; constexpr std::size_t kImplSize = 32; constexpr std::size_t kImplAlign = 8; utils::FastPimpl<JsonNative, kImplSize, kImplAlign> data_; }; Taxi C++ tricks 69 / 170
  • 70. До FastPimpl #include <formats/json.hpp> #include <third_party/json.hpp> Value::Value() : data_{std::make_unique<third_party::Json>()} {} Value::Value(Value&& other) = default; Value::Value& operator=(Value&& other) = default; Value::~Value() = default; std::size_t Value::Size() const { return data_->size(); } Taxi C++ tricks 70 / 170
  • 71. C FastPimpl #include <formats/json.hpp> #include <third_party/json.hpp> Value::Value() = default; Value::Value(Value&& other) = default; Value::Value& operator=(Value&& other) = default; Value::~Value() = default; std::size_t Value::Size() const { return data_->size(); } Taxi C++ tricks 71 / 170
  • 73. FastPimpl имплементация template <class T, size_t Size, size_t Alignment> class FastPimpl { public: template <class... Args> explicit FastPimpl(Args&&... args) { new (Ptr()) T(std::forward<Args>(args)...); } FastPimpl& operator=(FastPimpl&& rhs) { *Ptr() = std::move(*rhs); return *this; } Taxi C++ tricks 73 / 170
  • 74. FastPimpl имплементация template <class T, size_t Size, size_t Alignment> class FastPimpl { public: template <class... Args> explicit FastPimpl(Args&&... args) { new (Ptr()) T(std::forward<Args>(args)...); } FastPimpl& operator=(FastPimpl&& rhs) { *Ptr() = std::move(*rhs); return *this; } Taxi C++ tricks 74 / 170
  • 75. FastPimpl имплементация template <class T, size_t Size, size_t Alignment> class FastPimpl { public: template <class... Args> explicit FastPimpl(Args&&... args) { new (Ptr()) T(std::forward<Args>(args)...); } FastPimpl& operator=(FastPimpl&& rhs) { *Ptr() = std::move(*rhs); return *this; } Taxi C++ tricks 75 / 170
  • 76. FastPimpl имплементация template <class T, size_t Size, size_t Alignment> class FastPimpl { public: template <class... Args> explicit FastPimpl(Args&&... args) { new (Ptr()) T(std::forward<Args>(args)...); } FastPimpl& operator=(FastPimpl&& rhs) { *Ptr() = std::move(*rhs); return *this; } Taxi C++ tricks 76 / 170
  • 77. FastPimpl имплементация T* operator->() noexcept { return Ptr(); } const T* operator->() const noexcept { return Ptr(); } T& operator*() noexcept { return *Ptr(); } const T& operator*() const noexcept { return *Ptr(); } Taxi C++ tricks 77 / 170
  • 78. FastPimpl имплементация ~FastPimpl() noexcept { validate<sizeof(T), alignof(T)>(); Ptr()->~T(); } Taxi C++ tricks 78 / 170
  • 79. FastPimpl имплементация ~FastPimpl() noexcept { validate<sizeof(T), alignof(T)>(); Ptr()->~T(); } Taxi C++ tricks 79 / 170
  • 80. FastPimpl имплементация template <class T, size_t Size, size_t Alignment> class FastPimpl { // ... private: template <std::size_t ActualSize, std::size_t ActualAlignment> static void validate() noexcept { static_assert(Size == ActualSize, "Size and sizeof(T) mismatch"); static_assert(Alignment == ActualAlignment, "Alignment and alignof(T) mismatch"); } Taxi C++ tricks 80 / 170
  • 81. FastPimpl имплементация template <class T, size_t Size, size_t Alignment> class FastPimpl { // ... private: template <std::size_t ActualSize, std::size_t ActualAlignment> static void validate() noexcept { static_assert(Size == ActualSize, "Size and sizeof(T) mismatch"); static_assert(Alignment == ActualAlignment, "Alignment and alignof(T) mismatch"); } Taxi C++ tricks 81 / 170
  • 82. FastPimpl имплементация template <class T, size_t Size, size_t Alignment> class FastPimpl { // ... private: template <std::size_t ActualSize, std::size_t ActualAlignment> static void validate() noexcept { static_assert(Size == ActualSize, "Size and sizeof(T) mismatch"); static_assert(Alignment == ActualAlignment, "Alignment and alignof(T) mismatch"); } Taxi C++ tricks 82 / 170
  • 83. FastPimpl имплементация <source>: In instantiation of 'void FastPimpl<T, Size, Alignment>::validate() [with int ActualSize = 32; int ActualAlignment = 8; T = std::string; int Size = 8; int Alignment = 8]' Taxi C++ tricks 83 / 170
  • 84. Fast Pimpl В header file остаются только те части кода, которые не требуют знания о полном типе. Taxi C++ tricks 84 / 170
  • 85. Fast Pimpl В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы: Taxi C++ tricks 85 / 170
  • 86. Fast Pimpl В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы: ● Нужно написать 2 константы Taxi C++ tricks 86 / 170
  • 87. Fast Pimpl В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы: ● Нужно написать 2 константы Плюсы: Taxi C++ tricks 87 / 170
  • 88. Fast Pimpl В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы: ● Нужно написать 2 константы Плюсы: ● Не торчат наружу детали реализации Taxi C++ tricks 88 / 170
  • 89. Fast Pimpl В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы: ● Нужно написать 2 константы Плюсы: ● Не торчат наружу детали реализации ● Кеш дружелюбно Taxi C++ tricks 89 / 170
  • 90. Fast Pimpl В header file остаются только те части кода, которые не требуют знания о полном типе. Минусы: ● Нужно написать 2 константы Плюсы: ● Не торчат наружу детали реализации ● Кеш дружелюбно ● Минимум изменений в cpp файле Taxi C++ tricks 90 / 170
  • 93. Логирование #include <iostream> std::cerr << "Log message"; Taxi C++ tricks 93 / 170
  • 94. Логирование #include <iostream> std::cerr << timestamp() << "Log message"; Taxi C++ tricks 94 / 170
  • 95. Логирование #include <iostream> std::osyncstream{std::cerr} << timestamp() << "Log message"; Taxi C++ tricks 95 / 170
  • 96. Логирование struct LogHelper { LogHelper() { oss << timestamp(); } ~LogHelper() { std::cerr << oss.str(); } private: std::ostringstream oss; }; template <class T> LogHelper& operator<<(LogHelper& lh, const T& value) { lh.oss << value; return lh; } Taxi C++ tricks 96 / 170
  • 97. Логирование struct LogHelper { LogHelper() { oss << timestamp(); } ~LogHelper() { std::cerr << oss.str(); } private: std::ostringstream oss; }; template <class T> LogHelper& operator<<(LogHelper& lh, const T& value) { lh.oss << value; return lh; } Taxi C++ tricks 97 / 170
  • 98. Логирование struct LogHelper { LogHelper() { oss << timestamp(); } ~LogHelper() { std::cerr << oss.str(); } private: std::ostringstream oss; }; template <class T> LogHelper& operator<<(LogHelper& lh, const T& value) { lh.oss << value; return lh; } Taxi C++ tricks 98 / 170
  • 99. Логирование struct LogHelper { LogHelper() { oss << timestamp(); } ~LogHelper() { std::cerr << oss.str(); } private: std::ostringstream oss; }; template <class T> LogHelper& operator<<(LogHelper& lh, const T& value) { lh.oss << value; return lh; } Taxi C++ tricks 99 / 170
  • 100. Логирование struct LogHelper { LogHelper() { oss << timestamp(); } ~LogHelper() { std::cerr << oss.str(); } private: std::ostringstream oss; // Очень-очень медленно! }; template <class T> LogHelper& operator<<(LogHelper& lh, const T& value) { lh.oss << value; return lh; } Taxi C++ tricks 100 / 170
  • 102. Логирование (стало) private: FastStackBuffer buffer_; struct LazyInitedStream; std::optional<LazyInitedStream> lazy_; }; Taxi C++ tricks 102 / 170
  • 103. Логирование (стало) private: FastStackBuffer buffer_; // буффер использующий стек через std::array<char, 1024> struct LazyInitedStream; std::optional<LazyInitedStream> lazy_; }; Taxi C++ tricks 103 / 170
  • 104. Логирование (стало) private: FastStackBuffer buffer_; // буффер использующий стек через std::array<char, 1024> struct LazyInitedStream; // содержит std::ostream std::optional<LazyInitedStream> lazy_; }; Taxi C++ tricks 104 / 170
  • 105. Логирование (стало) private: FastStackBuffer buffer_; // буффер использующий стек через std::array<char, 1024> struct LazyInitedStream; // содержит std::ostream std::optional<LazyInitedStream> lazy_; // по умолчанию ничего не конструирует }; Taxi C++ tricks 105 / 170
  • 106. Логирование (было) template <class T> LogHelper& operator<<(LogHelper& lh, const T& value) { lh.oss << value; return lh; } Taxi C++ tricks 106 / 170
  • 107. Логирование (стало) template <typename T> LogHelper& LogHelper::operator<<(const T& value) { if constexpr (std::is_constructible<utils::string_view, T>::value) { buffer_.Put(value); } else if constexpr (std::is_base_of<std::exception, T>::value) { buffer_.PutException(value); } else { Stream() << value; } return *this; } Taxi C++ tricks 107 / 170
  • 108. Логирование (стало) template <typename T> LogHelper& LogHelper::operator<<(const T& value) { if constexpr (std::is_constructible<utils::string_view, T>::value) { buffer_.Put(value); } else if constexpr (std::is_base_of<std::exception, T>::value) { buffer_.PutException(value); } else { Stream() << value; } return *this; } Taxi C++ tricks 108 / 170
  • 109. Логирование (стало) template <typename T> LogHelper& LogHelper::operator<<(const T& value) { if constexpr (std::is_constructible<utils::string_view, T>::value) { buffer_.Put(value); } else if constexpr (std::is_base_of<std::exception, T>::value) { buffer_.PutException(value); } else { Stream() << value; } return *this; } Taxi C++ tricks 109 / 170
  • 110. Логирование (стало) template <typename T> LogHelper& LogHelper::operator<<(const T& value) { if constexpr (std::is_constructible<utils::string_view, T>::value) { buffer_.Put(value); } else if constexpr (std::is_base_of<std::exception, T>::value) { buffer_.PutException(value); } else { Stream() << value; } return *this; } Taxi C++ tricks 110 / 170
  • 111. Логирование (стало) private: FastStackBuffer buffer_; // буффер использующий стек через std::array<char, 1024> struct LazyInitedStream; // содержит std::ostream std::optional<LazyInitedStream> lazy_; // по умолчанию ничего не конструирует }; Taxi C++ tricks 111 / 170
  • 112. Логирование private: FastStackBuffer buffer_; struct LazyInitedStream { BufferStd sbuf; std::ostream ostr; explicit LazyInitedStream(FastStackBuffer& impl) : sbuf{impl}, ostr(&sbuf) {} }; std::optional<LazyInitedStream> lazy_; }; Taxi C++ tricks 112 / 170
  • 113. Логирование private: FastStackBuffer buffer_; struct LazyInitedStream { BufferStd sbuf; std::ostream ostr; explicit LazyInitedStream(FastStackBuffer& impl) : sbuf{impl}, ostr(&sbuf) {} }; std::optional<LazyInitedStream> lazy_; }; Taxi C++ tricks 113 / 170
  • 114. Логирование struct BufferStd final : public std::streambuf { explicit BufferStd(FastStackBuffer& impl) : impl_{impl} {} private: int_type overflow(int_type c) override; std::streamsize xsputn(const char_type* s, std::streamsize n) override; FastStackBuffer& impl_; }; Taxi C++ tricks 114 / 170
  • 115. Логирование struct BufferStd final : public std::streambuf { explicit BufferStd(FastStackBuffer& impl) : impl_{impl} {} private: int_type overflow(int_type c) override; std::streamsize xsputn(const char_type* s, std::streamsize n) override; FastStackBuffer& impl_; }; Taxi C++ tricks 115 / 170
  • 116. Логирование struct BufferStd final : public std::streambuf { explicit BufferStd(FastStackBuffer& impl) : impl_{impl} {} private: int_type overflow(int_type c) override; std::streamsize xsputn(const char_type* s, std::streamsize n) override; FastStackBuffer& impl_; }; Taxi C++ tricks 116 / 170
  • 117. Логирование struct BufferStd final : public std::streambuf { explicit BufferStd(FastStackBuffer& impl) : impl_{impl} {} private: int_type overflow(int_type c) override; std::streamsize xsputn(const char_type* s, std::streamsize n) override; FastStackBuffer& impl_; }; Taxi C++ tricks 117 / 170
  • 118. Логирование private: FastStackBuffer buffer_; std::optional<LazyInitedStream> lazy_; std::ostream& Stream() { if (!lazy_) { lazy_.emplace(buffer_); } return lazy_->ostr; } }; Taxi C++ tricks 118 / 170
  • 119. Логирование private: FastStackBuffer buffer_; std::optional<LazyInitedStream> lazy_; std::ostream& Stream() { if (!lazy_) { lazy_.emplace(buffer_); } return lazy_->ostr; } }; Taxi C++ tricks 119 / 170
  • 120. Логирование std::ostream& operator<<(std::ostream& os, const models::DriverInfo& info) { return os << "Id = " << info.id << ", name = " << info.name; } Taxi C++ tricks 120 / 170
  • 121. Логирование std::ostream& operator<<(std::ostream& os, const models::DriverInfo& info) { return os << "Id = " << info.id << ", name = " << info.name; } LogHelper& operator<<(LogHelper& lh, const models::DriverInfo& info) { return lh << "Id = " << info.id << ", name = " << info.name; } Taxi C++ tricks 121 / 170
  • 122. Логирование LogHelper& operator<<(LogHelper& lh, const models::DriverInfo& info) { return lh << "Id = " << info.id << ", name = " << info.name; } Taxi C++ tricks 122 / 170
  • 123. Логирование (бенчмарки) Было | Стало ------------------------------------- LogNumber<int> 682 ns | 321 ns LogNumber<long> 680 ns | 318 ns LogChar/8 690 ns | 334 ns LogChar/16 718 ns | 419 ns LogChar/512 2066 ns | 1928 ns LogStruct 812 ns | 685 ns Taxi C++ tricks 123 / 170 Note: в бенчмарках LogHelper() так же пишет уровень логирования, время, id корутины, id потока, id соединения; ~LogHelper() честно отрабатывает и отсылает данные в аналог std::cerr. Несмотря на эти «неоптимизируемые расходы», мы получаем прирост производительности в ~2 раза.
  • 124. Логирование (маленькая хитрость) Id id{42}; LogHelper lh{kDebug}; lh << staktrace() << id << ':' << db.FetchUserById(id); Taxi C++ tricks 124 / 170
  • 125. Логирование (маленькая хитрость) Id id{42}; LOG_DEBUG() << staktrace() << id << ':' << db.FetchUserById(id); Taxi C++ tricks 125 / 170
  • 126. Логирование (маленькая хитрость) #define LOG_DEBUG() if (kDebug >= CurrentLogLevel()) LogHelper{}.AsLValue() Taxi C++ tricks 126 / 170
  • 129. Логирование Плюсы: ● Нет динамических аллокаций Taxi C++ tricks 129 / 170
  • 130. Логирование Плюсы: ● Нет динамических аллокаций ● Быстрое форматирование без std::locale Taxi C++ tricks 130 / 170
  • 131. Логирование Плюсы: ● Нет динамических аллокаций ● Быстрое форматирование без std::locale ● Переключение на рантайме уровня логирования Taxi C++ tricks 131 / 170
  • 132. Логирование Плюсы: ● Нет динамических аллокаций ● Быстрое форматирование без std::locale ● Переключение на рантайме уровня логирования ● Не вычисляем лишнего Taxi C++ tricks 132 / 170
  • 134. Parse auto inf = json.As<models::DriverInfo>(); Taxi C++ tricks 134 / 170
  • 135. Parse auto inf = json.As<models::DriverInfo>(); auto inf = yaml.As<models::DriverInfo>(); Taxi C++ tricks 135 / 170
  • 136. Parse auto inf = json.As<models::DriverInfo>(); auto inf = yaml.As<models::DriverInfo>(); auto inf = bson.As<models::DriverInfo>(); Taxi C++ tricks 136 / 170
  • 137. Parse – точка кастомизации, которая должна искать в: Taxi C++ tricks 137 / 170
  • 138. Parse – точка кастомизации, которая должна искать в: ● namespce T Taxi C++ tricks 138 / 170
  • 139. Parse – точка кастомизации, которая должна искать в: ● namespce T ● где-то, где описаны общие парсеры Taxi C++ tricks 139 / 170
  • 140. Parse – точка кастомизации, которая должна искать в: ● namespce T ● где-то, где описаны общие парсеры ● где-то, где описаны формато-специфичные парсеры Taxi C++ tricks 140 / 170
  • 141. Parse namespace formats::json { struct Value { template <class T> T As() { return Parse(*this); // ??? } }; } // namespace formats::json Taxi C++ tricks 141 / 170
  • 142. Parse namespace formats::json { struct Value { template <class T> T As() { return Parse(*this); // ??? } }; } // namespace formats::json Taxi C++ tricks 142 / 170
  • 143. Parse namespace formats::json { struct Value { template <class T> T As() { return T::Parse(*this); } }; } // namespace formats::json Taxi C++ tricks 143 / 170
  • 144. Parse namespace formats::json { struct Value { template <class T> T As() { return T::Parse(*this); // std::vector<DriverInfo>, boost::optional<DriverInfo> :( } }; } // namespace formats::json Taxi C++ tricks 144 / 170
  • 145. Parse namespace formats::json { struct Value { template <class T> T As() { return Parse<T>(*this); } }; } // namespace formats::json Taxi C++ tricks 145 / 170
  • 146. Parse namespace formats::json { struct Value { template <class T> T As() { return Parse<T>(*this); // std::vector<DriverInfo>, boost::optional<DriverInfo> :( } }; } // namespace formats::json Taxi C++ tricks 146 / 170
  • 147. Parse namespace formats::json { struct Value { template <class T> T As() { T value; Parse(*this, value); return value; } }; } // namespace formats::json Taxi C++ tricks 147 / 170
  • 148. Parse namespace formats::json { struct Value { template <class T> T As() { T value; // не default constructible типы? Parse(*this, value); return value; } }; } // namespace formats::json Taxi C++ tricks 148 / 170
  • 149. Parse namespace formats::json { struct Value { template <class T> T As() { T* value = nullptr; return Parse(*this, value); } }; } // namespace formats::json Taxi C++ tricks 149 / 170
  • 150. Parse namespace formats::json { struct Value { template <class T> T As() { T* value = nullptr; // Отстрел ноги :( return Parse(*this, value); } }; } // namespace formats::json Taxi C++ tricks 150 / 170
  • 151. Parse — что делать? Taxi C++ tricks
  • 152. Parse #pragma once namespace formats::parse { template <class T> struct To {}; } // namespace formats::parse Taxi C++ tricks 152 / 170
  • 153. Parse namespace formats::json { struct Value { template <class T> T As() { return Parse(*this, parse::To<T>{}); } }; } // namespace formats::json Taxi C++ tricks 153 / 170
  • 154. ADL Taxi C++ tricks 154 / 170
  • 155. ADL Ищет функции с заданными именем в ● namespace аргументов функции Taxi C++ tricks 155 / 170
  • 156. ADL Ищет функции с заданными именем в ● namespace аргументов функции ● и namespace шаблонов аргументов функций Taxi C++ tricks 156 / 170
  • 157. Parse namespace formats::json { struct Value { template <class T> T As() { return Parse(*this, parse::To<T>{}); } }; } // namespace formats::json Taxi C++ tricks 157 / 170
  • 158. Parse namespace formats::json { struct Value { template <class T> T As() { return Parse(*this, parse::To<T>{}); // namespace formats::<json> } }; } // namespace formats::json Taxi C++ tricks 158 / 170
  • 159. Parse namespace formats::json { struct Value { template <class T> T As() { return Parse(*this, parse::To<T>{}); // namespace formats::parse } }; } // namespace formats::json Taxi C++ tricks 159 / 170
  • 160. Parse namespace formats::json { struct Value { template <class T> T As() { return Parse(*this, parse::To<T>{}); // namespace of T } }; } // namespace formats::json Taxi C++ tricks 160 / 170
  • 161. Parse namespace formats::parse { template <class Value, typename T> auto Parse(const Value& value, To<std::unordered_map<std::string, T>>); } // namespace formats::parse Taxi C++ tricks 161 / 170
  • 162. Parse namespace drivers::models { template <class Value> auto Parse(const Value& v, formats::parse::To<DriverInfo>); } // namespace drivers::models Taxi C++ tricks 162 / 170
  • 163. Parse namespace formats::bson { auto Parse(const bson::Value& v, parse::To<std::chrono::system_clock::time_point>); } // namespace formats::bson Taxi C++ tricks 163 / 170
  • 164. Parse Taxi C++ tricks 164 / 170
  • 165. Parse Плюсы Taxi C++ tricks 165 / 170
  • 166. Parse Плюсы: ● Одна функция на все форматы Taxi C++ tricks 166 / 170
  • 167. Parse Плюсы: ● Одна функция на все форматы ● Можно писать парсеры в своём namepsace Taxi C++ tricks 167 / 170
  • 168. Parse Плюсы: ● Одна функция на все форматы ● Можно писать парсеры в своём namepsace ● Нет мороки с linker или порядком заголовков Taxi C++ tricks 168 / 170