#quiz #explanation
Обычно вызывает ошибку компиляции, но в данном случае он используется в шаблоне, который нигде в программе не инстанцируется. Так что логично было бы ожидать, что в этом коде все хорошо и он выведет единицу. Однако, согласно C++20 и более ранним стадартам, поведение будет иным:
[temp.res.general#8]
The program is ill-formed, no diagnostic required, if:
— ...
— a hypothetical instantiation of a templated entity immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter...
static_assert(false) не зависит от шаблонных параметров и, если бы мы инстанцировали класс A немедленно после его объявления, он бы всегда вызывал ошибку компиляции (то есть, был ill-formed). Так что наша программа, согласно стандарту C++20, является IFNDR (ill-formed, no diagnostic required) — то есть, ее поведение неопределено.
Но в C++23 формулировки были изменены:
[temp.res.general#6]
The program is ill-formed, no diagnostics required, if:
— ...
— a hypothetical instantiation of a templated entity immediately following its definition would be ill-formed due to a construct (other than a static_assert-declaration that fails) that does not depend on a template parameter
Появилось исключение из правил именно для static_assert, так что в C++23 данный код корректен. На экран будет выведено 1
static_assert(false)[temp.res.general#8]
— ...
— a hypothetical instantiation of a templated entity immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter...
static_assert(false) не зависит от шаблонных параметров и, если бы мы инстанцировали класс A немедленно после его объявления, он бы всегда вызывал ошибку компиляции (то есть, был ill-formed). Так что наша программа, согласно стандарту C++20, является IFNDR (ill-formed, no diagnostic required) — то есть, ее поведение неопределено.
Но в C++23 формулировки были изменены:
The program is ill-formed, no diagnostics required, if:
— ...
— a hypothetical instantiation of a templated entity immediately following its definition would be ill-formed due to a construct (other than a static_assert-declaration that fails) that does not depend on a template parameter
Появилось исключение из правил именно для static_assert, так что в C++23 данный код корректен. На экран будет выведено 1
👍3
#quiz #code
Каким будет результат выполнения программы ниже? Делитесь своими мыслями в комментариях! Правильный ответ и его объяснение будут опубликованы в 18:00 по Москве.
Каким будет результат выполнения программы ниже? Делитесь своими мыслями в комментариях! Правильный ответ и его объяснение будут опубликованы в 18:00 по Москве.
#include <initializer_list>
#include <iostream>
class C {
public:
C() = default;
C(const C&) { std::cout << 1; }
};
void f(std::initializer_list<C> i) {}
int main() {
C c;
std::initializer_list<C> i{c};
f(i);
f(i);
}🔥2
Каким будет результат работы программы выше?
Anonymous Poll
36%
1
24%
11
30%
111
9%
Compilation error
#quiz #explanation
В данном коде копирование может произойти лишь в трех местах:
1. 2. Первый 3. Второй Так в каких же из них оно происходит? [dcl.init.list] определяет то, как создается следующим образом:
An object of type is constructed from an initializer list as if the implementation generated and materialized a prvalue of type “array of N const E”, where N is the number of elements in the initializer list. Each element of that array is copy-initialized with the corresponding element of the initializer list, and the object is constructed to refer to that array.
То есть, когда мы создаем , создается временный массив объектов типа , инициализируемый копированием. Так что в пункте 1 копирование действительно происходит и на экран выводится .
Далее мы дважды вызываем функцию , принимающую аргумент по значению. Так что для каждого из вызовов делается копия . Вызывает ли это копирование всех его элементов? Нет, так как не владеет своими элементами. Как было сказано в цитате выше, он лишь ссылается на временный массив.
И это дополнительно поясняется в [initializer_list.syn] :
Copying an initializer list does not copy the underlying elements
Ответ: 1
1.
std::initializer_list<C> i{c}
f(i)
f(i)
std::initializer_listAn object of type
std::initializer_list<E>std::initializer_list<E>То есть, когда мы создаем
iC1Далее мы дважды вызываем функцию
fstd::initializer_liststd::initializer_listИ это дополнительно поясняется в
Copying an initializer list does not copy the underlying elements
Ответ: 1
🔥3👏2
#proposals #resources
Каждый месяц комитет по стандартизации C++ (также известный как WG21) публикует свою „переписку“: все предложения (пропозалы) в стандарт за последний месяц, каждое из которых по результатам голосования среди членов WG21 может быть в него включено.
Совсем недавно, например, была опубликована переписка за сентябрь.
Какие пропозалы из нее вам кажутся наиболее интересными или каких полезных фич, по вашему мнению, в этом списке не хватает? Присоединяйтесь к обсуждению в комментариях!
Каждый месяц комитет по стандартизации C++ (также известный как WG21) публикует свою „переписку“: все предложения (пропозалы) в стандарт за последний месяц, каждое из которых по результатам голосования среди членов WG21 может быть в него включено.
Совсем недавно, например, была опубликована переписка за сентябрь.
Какие пропозалы из нее вам кажутся наиболее интересными или каких полезных фич, по вашему мнению, в этом списке не хватает? Присоединяйтесь к обсуждению в комментариях!
🔥2
#quiz #code
Каким будет результат выполнения программы ниже? Делитесь своими мыслями в комментариях! Правильный ответ и его объяснение будут опубликованы в 18:00 по Москве.
Каким будет результат выполнения программы ниже? Делитесь своими мыслями в комментариях! Правильный ответ и его объяснение будут опубликованы в 18:00 по Москве.
#include <type_traits>
#include <iostream>
using namespace std;
struct X {
int f() const&&{
return 0;
}
};
int main() {
auto ptr = &X::f;
cout << is_same_v<decltype(ptr), int()>
<< is_same_v<decltype(ptr), int(X::*)()>;
}🔥3
#quiz #explanation
Стандарт гласит:
[dcl.fct#8]
The return type, the parameter-type-list, the ref-qualifier, the cv-qualifier-seq, and the exception specification, but not the default arguments, are part of the function type.
То есть, ref-квалификаторы (в нашем случае для ) являются частью типа функции, так что тип это .
Ответ: 00
То есть, ref-квалификаторы (в нашем случае
const&&X::fptrint(X::*)() const&&Ответ: 00
👍2
C++ Moscow
Спасибо всем, кто посетил наш первый митап оффлайн и всем, кто ждал трансляции! К сожалению, по техническим причинам ее провести не удалось — однако, в течение недели доклады будут перезаписаны и опубликованы в хорошем качестве на нашем канале. Не всё получилось…
Работа работой и учеба учебой, но наши организаторы не дремлют и начинают строить более детальные планы на следующий митап..
А каким бы хотели видеть его вы? Поделитесь своими мыслями в комментариях!
А каким бы хотели видеть его вы? Поделитесь своими мыслями в комментариях!
❤🔥5🔥1
#quiz #code
Каким будет результат выполнения программы ниже? Делитесь своими мыслями в комментариях! Правильный ответ и его объяснение будут опубликованы в 18:00 по Москве.
Каким будет результат выполнения программы ниже? Делитесь своими мыслями в комментариях! Правильный ответ и его объяснение будут опубликованы в 18:00 по Москве.
#include <iostream>
using namespace std;
template <class T> void f(T) {
static int i = 0;
cout << ++i;
}
int main() {
f(1);
f(1.0);
f(1);
}👍4
Каким будет результат работы программы выше?
Anonymous Poll
12%
123
10%
111
76%
112
5%
Compilation error
#quiz #explanation
Стандарт гласит:
[temp.fct.spec]
Each function template specialization instantiated from a template has its own copy of any static variable.
То есть, каждое инстанцирование имеет свои копии статических переменных. В нашем коде имеется два инстанцирования: для и . Так что первый и третий (но не второй) вызов разделяют между собой одну статическую переменную.
Ответ: 112
То есть, каждое инстанцирование имеет свои копии статических переменных. В нашем коде имеется два инстанцирования: для
T = intT = doublefОтвет: 112
👍5
#digest
Подборка самых интересных новостей и материалов из мира C++ за последние две недели (18 сентября – 1 октября 2023)
Читать далее на Хабре
Подборка самых интересных новостей и материалов из мира C++ за последние две недели (18 сентября – 1 октября 2023)
Читать далее на Хабре
Хабр
C++ Дайджест №4 (18 сентября – 1 октября 2023)
Привет, Хабр! Сегодня я хочу вам представить подборку интересных новостей и материалов из мира C++ за последние две недели. Приятного чтения! ⚡️️ Новости и релизы LLVM 17.0.1 — Новый мажорный релиз,...
🔥4👍3
Вторая встреча московского сообщества программистов на C++ пройдет 19 ноября (Вс) с 15:20 до 18:00 по адресу Москва, Малый Конюшковский переулок, д. 2 (оффлайн + онлайн трансляция докладов)
Мы приглашаем всех принять в ней участие: поделиться своим опытом и экспертизой, просто хорошо пообщаться в кругу единомышленников
Кроме того, мы будем рады всем желающим выступить с мини-докладом продолжительностью до двадцати минут на любую тему, связанную с программированием на C++ (заявки принимаются до 15 октября включительно)
Свяжитесь с нами, и мы поможем вам на всех этапах: от подбора темы для выступления (если вы ещё с ней не определились) до подготовки красивой и ясной презентации
Заходите в чат по ссылке, регистрируйтесь на мероприятие (если вы планируете посетить его очно, то регистрация обязательна), и приходите на нашу встречу, будет интересно!
Мы приглашаем всех принять в ней участие: поделиться своим опытом и экспертизой, просто хорошо пообщаться в кругу единомышленников
Кроме того, мы будем рады всем желающим выступить с мини-докладом продолжительностью до двадцати минут на любую тему, связанную с программированием на C++ (заявки принимаются до 15 октября включительно)
Свяжитесь с нами, и мы поможем вам на всех этапах: от подбора темы для выступления (если вы ещё с ней не определились) до подготовки красивой и ясной презентации
Заходите в чат по ссылке, регистрируйтесь на мероприятие (если вы планируете посетить его очно, то регистрация обязательна), и приходите на нашу встречу, будет интересно!
🔥7
Корутины (сопрограммы) — одно из нововведений C++20, крайнего из на данных момент опубликованных стандартов. Хоть статей про них написано уже много, сами по себе они являются достаточно сложными для понимания и осознания: вместе с ними приходят сразу четыре новые сущности (promise object, coroutine handle, coroutine state, awaitable), которые программист должен постоянно держать в уме.
Множество статей и докладов рассматривают корутины на примере реализации генераторов (подобных питонячьим) — одного из самых элементарных и распространенных их приложений, что можно представить. Но что говорить, когда даже сам комитет по стандартизации C++ не смог реализовать нормальный генератор (то, что все же у него получилось, вошло в C++23 под названием std::generator)
Но не будем о грустном. Несмотря на то, что корутины тяжело писать, пользоваться ими легко и приятно! Будем радоваться, ведь всю эту неделю мы будем делиться с вами статьями и докладами, посвященными сопрограммам! Разберемся в них, во всех деталях, вместе
Множество статей и докладов рассматривают корутины на примере реализации генераторов (подобных питонячьим) — одного из самых элементарных и распространенных их приложений, что можно представить. Но что говорить, когда даже сам комитет по стандартизации C++ не смог реализовать нормальный генератор (то, что все же у него получилось, вошло в C++23 под названием std::generator)
Но не будем о грустном. Несмотря на то, что корутины тяжело писать, пользоваться ими легко и приятно! Будем радоваться, ведь всю эту неделю мы будем делиться с вами статьями и докладами, посвященными сопрограммам! Разберемся в них, во всех деталях, вместе
🔥5👍2
#cpp20 #coroutines
Начнем же наш путь! Первые статьи в нашем меню:
1. Habr: Корутины C++20 в примерах
2. Habr: Готовимся к С++20. Coroutines TS на реальном примере
Обе они вводные, но если первая рассматривает исключительно то, как корутины (кем-то за нас написанные) использовать, то вторая уже слегка приоткрывает завесу: что у них под капотом?
Если эти статьи кажутся вам слишком лайтовыми, оставайтесь на связи, впереди нас ждет хардкор!
Начнем же наш путь! Первые статьи в нашем меню:
1. Habr: Корутины C++20 в примерах
2. Habr: Готовимся к С++20. Coroutines TS на реальном примере
Обе они вводные, но если первая рассматривает исключительно то, как корутины (кем-то за нас написанные) использовать, то вторая уже слегка приоткрывает завесу: что у них под капотом?
Если эти статьи кажутся вам слишком лайтовыми, оставайтесь на связи, впереди нас ждет хардкор!
🔥5👍2
#cpp20 #coroutines
Не будем вас томить, следующие статьи и доклады раскрывают корутины наиболее детально:
1. 🇷🇺 Habr: Корутины в C++20 — что это и как с ними работать
2. 🇷🇺 Habr: C++20. Coroutines
3. 🇬🇧 David Mazières: My tutorial and take on C++20 coroutines
4. 🇬🇧 Lewis Baker: Asymmetric Transfer
Выбирайте любую по своим языковым предпочтениям — не ошибетесь. Но как наиболее фундаментальный и всеобъемлющий труд я рекомендую серию статей Assymetric Transfer (Lewis Baker). Это лонг-лонг рид, но он абсолютно того стоит: теоретические основы корутин; механизмы их работы: operator coawait, promisetype, симметричный перенос; какие преобразования над нашим корутинным кодом выполняет компилятор — все это раскрывается во всех деталях, и вряд ли после его прочтения у вас останется хоть один вопрос о том, как работают сопрограммы.
Если же вы больше предпочитаете видео, то на тему корутин есть несколько хороших докладов:
1. 🇬🇧 Andreas Fertig: C++20’s Coroutines for Beginners — рассматривающий корутины на основе примеров;
2. 🇬🇧 Andreas Weis: Deciphering C++ Coroutines - A Diagrammatic Coroutine Cheat Sheet — больше углубляющийся в анатомию корутин и проводящий связи между их компонентами, как они между собой взаимодействуют.
И две прекрасные лекции, детальные и с прекрасной подачей:
1. 🇷🇺 Константин Владимиров: Сопрограммы, часть 1 — Обзор разновидностей сопрограмм и их основных частей, дополненный множеством интересных упражнений: собственный генератор, исследование объектов ожидания и разбор тонких и сложных проблем;
2. 🇷🇺 Константин Владимиров: Сопрограммы, часть 2 — Варианты симметрии в корутинах, их применение в конечных автоматах, многопоточности и асинхронности.
И это все, конечно, очень хорошо, но как дела обстоят с инфраструктурой для корутин: ведь обычно нам хочется использовать готовые классы generator, task и так далее, а не писать их самостоятельно, и насколько хорошо их поддерживают компиляторы? Поговорим об этом в следующий раз!
Не будем вас томить, следующие статьи и доклады раскрывают корутины наиболее детально:
1. 🇷🇺 Habr: Корутины в C++20 — что это и как с ними работать
2. 🇷🇺 Habr: C++20. Coroutines
3. 🇬🇧 David Mazières: My tutorial and take on C++20 coroutines
4. 🇬🇧 Lewis Baker: Asymmetric Transfer
Выбирайте любую по своим языковым предпочтениям — не ошибетесь. Но как наиболее фундаментальный и всеобъемлющий труд я рекомендую серию статей Assymetric Transfer (Lewis Baker). Это лонг-лонг рид, но он абсолютно того стоит: теоретические основы корутин; механизмы их работы: operator coawait, promisetype, симметричный перенос; какие преобразования над нашим корутинным кодом выполняет компилятор — все это раскрывается во всех деталях, и вряд ли после его прочтения у вас останется хоть один вопрос о том, как работают сопрограммы.
Если же вы больше предпочитаете видео, то на тему корутин есть несколько хороших докладов:
1. 🇬🇧 Andreas Fertig: C++20’s Coroutines for Beginners — рассматривающий корутины на основе примеров;
2. 🇬🇧 Andreas Weis: Deciphering C++ Coroutines - A Diagrammatic Coroutine Cheat Sheet — больше углубляющийся в анатомию корутин и проводящий связи между их компонентами, как они между собой взаимодействуют.
И две прекрасные лекции, детальные и с прекрасной подачей:
1. 🇷🇺 Константин Владимиров: Сопрограммы, часть 1 — Обзор разновидностей сопрограмм и их основных частей, дополненный множеством интересных упражнений: собственный генератор, исследование объектов ожидания и разбор тонких и сложных проблем;
2. 🇷🇺 Константин Владимиров: Сопрограммы, часть 2 — Варианты симметрии в корутинах, их применение в конечных автоматах, многопоточности и асинхронности.
И это все, конечно, очень хорошо, но как дела обстоят с инфраструктурой для корутин: ведь обычно нам хочется использовать готовые классы generator, task и так далее, а не писать их самостоятельно, и насколько хорошо их поддерживают компиляторы? Поговорим об этом в следующий раз!
🔥9👍3
#cpp20 #coroutines
Если говорить об инфраструктуре и поддержке корутин в компиляторах, то, к сожалению, C++20 не принес совершенно никакой высокоуровневой библиотечной поддержки; все, что мы имеем:
И комитет не дремлет; в C++23 был принят пропозал (не реализованный еще ни в одном компиляторе):
1. 🇬🇧 std::generator: Synchronous Coroutine Generator for Ranges, описывающий корутинный генератор:
1. 🇬🇧 std::lazy: Coroutine for Deferred Execution, предлагающий довольно минималистичный класс для представления асинхронных вычислений:
И на этом всё. Больше никакой поддержки в стандартной библиотеке пока что не предвидится. К счастью, уже написано несколько библиотек, предоставляющих помимо высокоуровневых корутинных примитивов средства для планирования (scheduling) задач и неблокирующего I/O:
1. 🇬🇧 Facebook: Folly::Coro — Асинхронный корутинный фреймворк от Facebook, быстрый и помимо всего поддерживающий асинхронные примитивы синхронизации.
2. 🇬🇧 Lewis Baker: CppCoro — Прародитель всех корутинных фреймворков. К сожалению, уже мертвый, но ввиду своей большой популярности продолживший жизнь через форки и многочисленных идейных продолжателей: [1], [2], [3], [4], [5].
3. 🇬🇧 Dan Vrátil: QCoro — Если вы хотите использовать в Qt корутины вместо сигналов.
А какие библиотеки используете вы? Или вы уже успели написать все самостоятельно? 😉
Если говорить об инфраструктуре и поддержке корутин в компиляторах, то, к сожалению, C++20 не принес совершенно никакой высокоуровневой библиотечной поддержки; все, что мы имеем:
coroutine_traits, coroutine_handle. И это, конечно, прекрасно: мы можем с помощью них писать свои сопрограммы. Однако не всем в удовольствие писать низкоуровневый код, хотелось бы иметь для прикладного использования и готовенькое.И комитет не дремлет; в C++23 был принят пропозал (не реализованный еще ни в одном компиляторе):
1. 🇬🇧 std::generator: Synchronous Coroutine Generator for Ranges, описывающий корутинный генератор:
std::generator<int> iota(int start = 0) {
while (true)
co_yield start++;
}
void f() {
for (auto i: iota() | std::views::take(3))
std::cout << i << ' '; // Печатает 0 1 2
}
Кроме того, прямо сейчас в комитете рассматривается:1. 🇬🇧 std::lazy: Coroutine for Deferred Execution, предлагающий довольно минималистичный класс для представления асинхронных вычислений:
lazy<int> coro() {
int result = 0;
while (int v = co_await async_read())
result += v;
co_return result;
}
void f() {
lazy<int> task = coro(); // Получим объект корутины
co_await task; // А теперь наконец ее исполним
}
К сожалению, далеко не факт, примут ли это предложение в C++26: как оно было подано в 2022-ом, так с тех пор и нет никакого прогресса в продвижениии к его принятию.И на этом всё. Больше никакой поддержки в стандартной библиотеке пока что не предвидится. К счастью, уже написано несколько библиотек, предоставляющих помимо высокоуровневых корутинных примитивов средства для планирования (scheduling) задач и неблокирующего I/O:
1. 🇬🇧 Facebook: Folly::Coro — Асинхронный корутинный фреймворк от Facebook, быстрый и помимо всего поддерживающий асинхронные примитивы синхронизации.
2. 🇬🇧 Lewis Baker: CppCoro — Прародитель всех корутинных фреймворков. К сожалению, уже мертвый, но ввиду своей большой популярности продолживший жизнь через форки и многочисленных идейных продолжателей: [1], [2], [3], [4], [5].
3. 🇬🇧 Dan Vrátil: QCoro — Если вы хотите использовать в Qt корутины вместо сигналов.
А какие библиотеки используете вы? Или вы уже успели написать все самостоятельно? 😉
🔥6👍2
Вот и закончилась неделя корутин. Надеемся, наши материалы оказались не только интересны, но и полезны! И, так как это были первые посты в экспериментальном формате «Неделя X», мы приглашаем всех поделиться в комментариях своим мнением: понравился ли вам формат, как его можно было бы улучшить и какую неделю вы хотите видеть следующей послеследующей?
Кроме того, мы рады напомнить, что сегодня последний день приёма заявок желающих выступить с докладом на ближайшем митапе! А значит, следующая неделя будет неделей анонсов докладов C++ Moscow №2!
Кроме того, мы рады напомнить, что сегодня последний день приёма заявок желающих выступить с докладом на ближайшем митапе! А значит, следующая неделя будет неделей анонсов докладов C++ Moscow №2!
🔥6❤2
Чуть больше чем месяц остался до нашей встречи и мы рады познакомить вас с одним из запланированных докладов: Илья Быконя расскажет нам, как подружить Qt и корутины!
🔥6
Корутины и Qt. Библиотека QCoro
Qt появился уже почти 30 лет назад. Хотя фреймворк и сейчас поддерживается и получает крупные обновления как от разработчиков, так и от комьюнити, его событийно-ориентированная система заставляет нас использовать вереницы коллбеков или множество вложенных лямбд и на сегодняшний день выглядит достаточно громоздко в сравнении с другими языками и даже библиотеками C++ (привет, userver).
Библиотека QCoro призвана привнести возможности корутин в событийную систему Qt и позволить избежать описания лишнего кода, одноразовых функций и логики перекладывания данных из метода в метод.
Библиотека не ломает обратную совместимость. Все старые классы, по типу QNetworkManager, QFuture или классов IO-системы полностью совместимы с QCoro. Достаточно лишь заменить QObject::connect с коллбеком на co_await и узреть магию.
При этом библиотека надёжна и признана мировым сообществом. Например, она входит в официальные репозитории (extra) для Manjaro Linux, а значит, проходит несколько этапов проверок прежде, чем попасть в эти репозитории.
Qt появился уже почти 30 лет назад. Хотя фреймворк и сейчас поддерживается и получает крупные обновления как от разработчиков, так и от комьюнити, его событийно-ориентированная система заставляет нас использовать вереницы коллбеков или множество вложенных лямбд и на сегодняшний день выглядит достаточно громоздко в сравнении с другими языками и даже библиотеками C++ (привет, userver).
Библиотека QCoro призвана привнести возможности корутин в событийную систему Qt и позволить избежать описания лишнего кода, одноразовых функций и логики перекладывания данных из метода в метод.
Библиотека не ломает обратную совместимость. Все старые классы, по типу QNetworkManager, QFuture или классов IO-системы полностью совместимы с QCoro. Достаточно лишь заменить QObject::connect с коллбеком на co_await и узреть магию.
При этом библиотека надёжна и признана мировым сообществом. Например, она входит в официальные репозитории (extra) для Manjaro Linux, а значит, проходит несколько этапов проверок прежде, чем попасть в эти репозитории.
🔥9