Виталий Ткаченко - Обратные вызовы в C++

Здесь есть возможность читать онлайн «Виталий Ткаченко - Обратные вызовы в C++» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2021, Издательство: Array SelfPub.ru, Жанр: Программирование, на русском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Обратные вызовы в C++: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Обратные вызовы в C++»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

В практике разработки ПО зачастую встает задача динамической модификации программного кода в зависимости от текущих или настраиваемых значений параметров. Для решения этой задачи широко используются обратные вызовы. В языке C++ обратные вызовы реализуются различными способами, и далеко не всегда очевидно, какой из них лучший для конкретной ситуации. В книге рассмотрены теоретические и практические аспекты организации обратных вызовов, проанализированы достоинства и недостатки различных реализаций, выработаны рекомендации по выбору в зависимости от требований к проектируемому ПО. В первую очередь книга предназначена для программистов среднего (middle) уровня, т.е. тех, кто уже достаточно хорошо знает язык C++, но хотел бы расширить и углубить свои знания в области проектирования и дизайна. В определенной степени она также будет интересна опытным разработчикам, с одной стороны, как систематизация знаний, с другой стороны, как источник идей и методов для решения практических задач.

Обратные вызовы в C++ — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Обратные вызовы в C++», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

5.3.4. Способ 3: объекты и данные в кортежах

При использовании данного способа реализация практически повторяет рассмотренную в предыдущем параграфе, только вместо пакета данных будет использоваться кортеж (Листинг 70).

Листинг 70. Распределение при упаковке объектов и данных в кортежи

template // (1)

struct TupleIterator3

{

static void IterateTupleItem(CallObjects& callObjects, CallData& callData) // (2)

{

const std::size_t idx = std::tuple_size_v – Index; // (3)

std::apply(std::get(callObjects), callData); // (4)

TupleIterator3::IterateTupleItem(callObjects, callData); // (5)

}

};

template // (6)

struct TupleIterator3<0, CallObjects, CallData> // (7)

{

static void IterateTupleItem(CallObjects& callObjects, CallData& callData) // (8)

{

}

};

template // (9)

void Distribute3(std::tuple callObjects, std::tuple callData) // (10)

{

TupleIterator3 // (11)

<

sizeof…(CallObjects), // (12)

std::tuple, // (13)

std::tuple // (14)

>

::IterateTupleItem(callObjects, callData); // (15)

}

По сравнению с Листинг 69 п. 5.3.3 изменения здесь следующие. Входными параметрами распределяющей функции (строка 10) являются кортеж объектов и кортеж данных (ранее параметр для данных задавался пакетом). В объявлениях шаблонов структур для обхода кортежа (строки 1, 6) параметр, определяющий данные вызова, объявляется как тип (ранее это был пакет). Вызов объекта (строка 4) осуществляется через std::apply(ранее объект вызывался непосредственно). И еще здесь изменены имена структур, чтобы избежать конфликта имен с предыдущей реализацией.

5.3.5. Сравнение способов

В Листинг 71 приведен пример распределения вызовов с использованием различных способов настройки сигнатуры, в качестве данных выступают два числовых значения.

Листинг 71. Распределение вызовов с заданной сигнатурой

void ExternalHandler(int eventID, int contextID) {}

struct FO

{

void callbackHandler(int eventID, int contextID) {}

void operator() (int eventID, int contextID) {}

};

int main()

{

int eventID = 0, contextID = 1;

FO fo;

auto lambda = [](int eventID, int contextID) {};

auto cb2cl = std::bind(&FO::callbackHandler, fo, _1, _2);

Distribute1(std::tuple(eventID, contextID), ExternalHandler, fo, cb2cl, lambda);

Distribute2(std::tuple(ExternalHandler, fo, cb2cl, lambda), eventID, contextID);

Distribute3(std::tuple(ExternalHandler, fo, cb2cl, lambda), std::tuple(eventID, contextID));

}

С точки зрения эффективности все три способа, в общем-то, равноценны. С точки зрения дизайна можно сказать следующее: первый способ самый простой в реализации; второй способ позволяет легко модифицировать код для сбора дополнительной информации при выполнении вызовов; третий способ позволяет передавать дополнительные параметры в функцию распределения, если это необходимо.

5.3.6. Настройка сигнатуры для перенаправления

В рассмотренных выше примерах мы предполагали, что все получатели используют одну и ту же сигнатуру вызова. Но что делать, если они имеют разные сигнатуры? Нам необходимо разработать какой-то объект, который бы обеспечивал следующее: настройку входной сигнатуры, в которую передаются данные вызова; настройку выходной сигнатуры, которая определяется получателем; преобразование одной сигнатуры в другую. По сути дела, необходимо обеспечить перенаправление вызовов, что решается с помощью инструментов STL, а именно – объектов связывания (см. п. 4.6.2). В этом случае в функцию распределителя вместо объекта-получателя передается объект-связывание, который осуществляет перенаправление вызова с заданной сигнатурой. Пример реализации приведен в Листинг 72; здесь в качестве распределяющей функции используется реализация из Листинг 69 п. 5.3.3.

Листинг 72. Перенаправление вызовов с настройкой сигнатуры

void NativeHandler(int eventID)

{

}

void ExternalHandler(int eventID, int contextID)

{

}

struct FO

{

void operator() (int eventID, int contextID) {}

void callbackHandler(int eventID, int contextID) {}

};

int main()

{

int eventID = 0, contextID = 0;

FO fo;

auto lambda = [](int eventID, int contextID) {};

Distribute2(std::tuple( // (1)

NativeHandler, // (2)

std::bind(ExternalHandler, std::placeholders::_1, contextID), // (3)

std::bind(&FO:: callbackHandler, fo, std::placeholders::_1, contextID), // (4)

std::bind(&FO::operator(), fo, std::placeholders::_1, contextID), // (5)

std::bind(lambda, std::placeholders::_1, contextID) // (6)

),

eventID // (7)

);

}

Входными аргументами распределяющей функции служат кортеж объектов вызова (объявлен в строке 1) и данные вызова (строка 7). В строке 2 в кортеж передается объект вызова с сигнатурой, совпадающей с исходной. В строке 3 передается объект связывания (результат вызова std::bind), в котором исходный вызов перенаправляется в назначенную функцию ExternalHandler. В строке 4 объект связывания перенаправляет вызов в метод-член структуры, в строке 5 – в перегруженный оператор, в строке 6 – в лямбда-выражение.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Обратные вызовы в C++»

Представляем Вашему вниманию похожие книги на «Обратные вызовы в C++» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Обратные вызовы в C++»

Обсуждение, отзывы о книге «Обратные вызовы в C++» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x