_Result_base


Я медленно сдуваю пыль с процессора отладочной платы. Нежно поглаживаю паяльником вздыбившиеся дорожки. Аккуратно убираю волосы с гребенчатого разъема. Да что из себя пионера-то корчить, никогда платой не причесывался?
Резко вставляю штекер в гнездо, плата от неожиданности начинает беспорядочно моргать всеми светодиодами. Другой рукой открываю давно уже написанный пример:
𝚟𝚘𝚒𝚍 𝚏𝚞𝚝𝚞𝚛𝚎𝙴𝚡𝚊𝚖𝚙𝚕𝚎() {
𝚜𝚝𝚍::𝚏𝚞𝚝𝚞𝚛𝚎<𝚒𝚗𝚝> 𝚏𝟸 = 𝚜𝚝𝚍::𝚊𝚜𝚢𝚗𝚌(𝚜𝚝𝚍::𝚕𝚊𝚞𝚗𝚌𝚑::𝚊𝚜𝚢𝚗𝚌, []{ 𝚛𝚎𝚝𝚞𝚛𝚗 𝟺𝟸; });
𝚏𝟸.𝚠𝚊𝚒𝚝();
𝚒𝚗𝚝 𝚡 = 𝚏𝟸.𝚐𝚎𝚝();
}
Я не стал убирать wait(), хотя get уже заставит текущий поток ждать, но пусть останется для наглядности.
Пример не самый простой, все-таки async с порождением отдельного потока под выполнение задачи. Попробуем его собрать. Жмем кнопку и ждем чуда.
Чуда не случилось:
𝚞𝚗𝚍𝚎𝚏𝚒𝚗𝚎𝚍 𝚛𝚎𝚏𝚎𝚛𝚎𝚗𝚌𝚎 𝚝𝚘 `𝚜𝚝𝚍::__𝚏𝚞𝚝𝚞𝚛𝚎_𝚋𝚊𝚜𝚎::_𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎::_𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎()'
𝚞𝚗𝚍𝚎𝚏𝚒𝚗𝚎𝚍 𝚛𝚎𝚏𝚎𝚛𝚎𝚗𝚌𝚎 𝚝𝚘 `𝚜𝚝𝚍::__𝚏𝚞𝚝𝚞𝚛𝚎_𝚋𝚊𝚜𝚎::_𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎::~_𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎()'
Оказалось, что мы забыли реализовать конструктор и деструктор обертки результирующего типа _Result_base.
Это вложенный базовый класс __future_base.
𝚜𝚝𝚛𝚞𝚌𝚝 _𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎 {
𝚎𝚡𝚌𝚎𝚙𝚝𝚒𝚘𝚗_𝚙𝚝𝚛
_𝙼_𝚎𝚛𝚛𝚘𝚛;
𝚟𝚒𝚛𝚝𝚞𝚊𝚕 𝚟𝚘𝚒𝚍 _𝙼_𝚍𝚎𝚜𝚝𝚛𝚘𝚢() = 𝟶;
𝚜𝚝𝚛𝚞𝚌𝚝 _𝙳𝚎𝚕𝚎𝚝𝚎𝚛 {
𝚟𝚘𝚒𝚍 𝚘𝚙𝚎𝚛𝚊𝚝𝚘𝚛()(_𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎* __𝚏𝚛) 𝚌𝚘𝚗𝚜𝚝 { __𝚏𝚛->_𝙼_𝚍𝚎𝚜𝚝𝚛𝚘𝚢(); }
};
𝚙𝚛𝚘𝚝𝚎𝚌𝚝𝚎𝚍:
_𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎();
𝚟𝚒𝚛𝚝𝚞𝚊𝚕 ~_𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎();
};
Вложен он не просто так, его потомки используются для хранения результатов вычисления. Структура _Deleter внутри явно сигнализирует: "Используй меня в умном указателе!". И точно, в другом вложенном и хорошо знакомом нам классе _State_baseV2 есть член _M_result типа _Ptr:
𝚝𝚎𝚖𝚙𝚕𝚊𝚝𝚎<𝚝𝚢𝚙𝚎𝚗𝚊𝚖𝚎 _𝚁𝚎𝚜>
𝚞𝚜𝚒𝚗𝚐 _𝙿𝚝𝚛 = 𝚞𝚗𝚒𝚚𝚞𝚎_𝚙𝚝𝚛<_𝚁𝚎𝚜, _𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎::_𝙳𝚎𝚕𝚎𝚝𝚎𝚛>;
Тут вся премудрость в выборе правильного наследника. Есть обычный, подходящий для нормальных объектов
𝚝𝚎𝚖𝚙𝚕𝚊𝚝𝚎<𝚝𝚢𝚙𝚎𝚗𝚊𝚖𝚎 _𝚁𝚎𝚜>
𝚜𝚝𝚛𝚞𝚌𝚝 _𝚁𝚎𝚜𝚞𝚕𝚝 : _𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎 {...};
Если нужно задействовать пользовательский аллокатор при формировании результата, то есть еще такой класс:
𝚝𝚎𝚖𝚙𝚕𝚊𝚝𝚎<𝚝𝚢𝚙𝚎𝚗𝚊𝚖𝚎 _𝚁𝚎𝚜, 𝚝𝚢𝚙𝚎𝚗𝚊𝚖𝚎 _𝙰𝚕𝚕𝚘𝚌>
𝚜𝚝𝚛𝚞𝚌𝚝 _𝚁𝚎𝚜𝚞𝚕𝚝_𝚊𝚕𝚕𝚘𝚌 𝚏𝚒𝚗𝚊𝚕 : _𝚁𝚎𝚜𝚞𝚕𝚝<_𝚁𝚎𝚜>, _𝙰𝚕𝚕𝚘𝚌 {...};
где можно переопределить _M_destroy, который аккуратно удалит объект, учитывая его аллокаторную природу.
Не будем забывать и частичные специализации для ссылочных типов и для void. Да, есть и такое, это действенный метод избежать переусложнения кода.
А, забыл сказать, чтоб исправить ошибку, достаточно написать в каком-нибудь новом файле future.cpp
𝚗𝚊𝚖𝚎𝚜𝚙𝚊𝚌𝚎 𝚜𝚝𝚍 {
__𝚏𝚞𝚝𝚞𝚛𝚎_𝚋𝚊𝚜𝚎::_𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎::_𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎() {}
__𝚏𝚞𝚝𝚞𝚛𝚎_𝚋𝚊𝚜𝚎::_𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎::~_𝚁𝚎𝚜𝚞𝚕𝚝_𝚋𝚊𝚜𝚎() {}
}
Базовый класс не содержит никаких данных, кроме указателя на исключение _M_error, собственно, ничего и не нужно делать в их деструкторе и конструкторе.
Вот теперь прошивка прекрасно собирается и запускается на плате, и даже выдает правильный результат. Это значит, что все ранее реализованные примитивы и потоки сработали. Запахло успехом.
Просмотры: 33
Открыть в MAX Сообщить о неточности

Репосты публикации

Публикация канала

Сообщить о неточности

Опишите, что нужно исправить. Если есть источник, добавьте ссылку.

Вы покидаете datool.ru

Ссылка ведёт на внешний сайт. datool.ru не отвечает за его содержимое — проверьте адрес, прежде чем вводить пароли или платёжные данные.

Переход через 10 с

Перейти