Так, и ошибка у нас в ...
struct A
{
unsigned int m_a = 1337u;
};
int main()
{
static_assert( std::is_invocable<decltype( &A::m_a ), A>::value ); // 1
std::invoke( &A::m_a, A() ); // 2
return 0;
}
Bonne nuit! Знаю, что посты стали крайне редкими, а обещанные статьи, все никак не дойдут до публикации. Так происходит потому, что я очень-очень-очень люблю свою работу, о чем не стесняюсь рассказывать публично [https://vk.com/id533333]. Работы сложной, интересной и ответственной очень-очень-очень много, и даже сейчас, на ночь глядя, я работаю в офисе :) Тем не менее, кое-что для вас у меня есть:
Дан такой кусочек C++ кода:
UPD: под implementation defined также можно рассматривать conditionally-supported поведение.
Дан такой кусочек C++ кода:
void call_me()
{}
void* ptr_1 = static_cast <void*>( call_me ); // 1
...
void* ptr_2 = reinterpret_cast<void*>( call_me ); // 2
...
reinterpret_cast<void(*)()>( ptr_2 );
// 3
Определите верное описание происходящего.UPD: под implementation defined также можно рассматривать conditionally-supported поведение.
❤1
Говоря о выше написанном, разберем, о том, почему же последние два случая - implementation defined.
Стандарт разделяет понятия pointer to object и pointer to function. Вот, что известно о void*:
P.S: До C++11 такое приведение было illegal.
#cxx #cxx11
Стандарт разделяет понятия pointer to object и pointer to function. Вот, что известно о void*:
The type of a pointer to void or a pointer to an object type is called an object pointer type.
А вот что известно о reinterpret_cast преобразовании function pointer to an object pointer:Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning of such a conversion is implementation-defined, except that if an implementation supports conversions in both directions, converting a prvalue of one type to the other type and back, possibly with different cv-qualification, shall yield the orignal pointer value.
Интересным здесь является появление поведения, именуемого conditionally-supported
[defns.cond.supp] conditionally-supported - "program construct that an implementation is not required to support"
[defns.impl.defined] implementation-defined behavior - "behavior, for a well-formed program construct and correct data, that depends on the implementation and that each implementation documents"
То есть, если описанное не поддерживается, то обязательно должна быть диагностика этого случая.P.S: До C++11 такое приведение было illegal.
#cxx #cxx11
Мы тут, кстати, решили потестировать 'новый' и 'уникальный', безумно 'умный' сервис от Артемия Лебедева - Николай Иронов aka дизайнер, художник и нейросеть для генерации логотипов. Вот, что вышло(коротко - shit merged):
https://tjournal.ru/internet/215408-nikolay-ironov-okolo-tehnicheskiy-obzor-na-to-kak-ya-vykinul-9900
#interesting
https://tjournal.ru/internet/215408-nikolay-ironov-okolo-tehnicheskiy-obzor-na-to-kak-ya-vykinul-9900
#interesting
TJ
Николай Иронов — около-технический обзор на то как я выкинул 9900 — Интернет на TJ
Напоминание: чукча не писатель, текст написан за час на коленке чтобы не дать мажору украсть ваши 9900 рассказав про нейросеть и уникальные крутые логотипы.
Давно уж обещал написать про забавный трюк, и вот... она перед вами, коробка с карандашами...:
https://habr.com/ru/post/522820/
#interesting #publication #c #cxx #optimization
https://habr.com/ru/post/522820/
#interesting #publication #c #cxx #optimization
Хабр
Приключение чисел в ASCII-ландии. Часть 0x01u. Беззнаковые целые числа
Думаю, с переводом чисел в ASCII строки в своей жизни сталкивался каждый программист. В свое время для меня было удивительно узнать, что перевод десятичной цифры в равнозначный ASCII символ – операция...
Привет, я снова на связи. На большие посты / статьи - нету времени, поэтому, я решил сделать новую рубрику - 'Содержит ли данный кусок кода, баг?'. Суть простая: я скидываю кусок C/C++ кода и опросник из двух вариантов ответа - есть баг, или нету бага. Ваше дело, выбрать верный. Да, скидывать код без багов я также собираюсь - и буду делать это очень умело :)
struct elem_t
{
uint64_t prev_time;
uint64_t stats;
mutex_t mtx;
};
....
// Код некоторой функции, вызываемой в разных потоках. elem aka elem_t - шарим между потоками.
uint64_t curr_time = get_current_time_ns();
elem->mtx.l();
elem->stats += curr_time - elem->prev_time;
elem->prev_time = curr_time;
elem->mtx.u();
❤1
Да, в коде выше есть баг, а именно Unsigned Overflow.
В однопоточном варианте этот баг себя никак не проявит: ожидаемо, функция get_current_time_ns будет выдавать значения не меньше значений полученных при предыдущих её вызовах, и каждое из этих значений будет записано в поле prev_time, объекта elem, после чего разность curr_time и prev_time будет посчитана без каких-либо проблем. В многопоточном же сценарии все не так радужно и баг дает о себе знать:
Пусть у нас есть два потока и оба вошли в заданную функцию. При этом до блокировки каждый из них получил результат функции get_current_time_ns: 0 и 1 соответственно. Пусть в блокировку входит поток у которого значение данной функции - единица(обозначу его как A), а поток с значением 0, ожидает разблокировки(обозначу его как B). В итоге, поток A при выполнении присвоит elem->prev_time единицу и даст старт потоку B, который, имея значение curr_time = 0, выполнит вычитание: 0 - 1->unsigned overflow.
@ioann_V для связи.
#multithreading #sync #cxx #hardcore
В однопоточном варианте этот баг себя никак не проявит: ожидаемо, функция get_current_time_ns будет выдавать значения не меньше значений полученных при предыдущих её вызовах, и каждое из этих значений будет записано в поле prev_time, объекта elem, после чего разность curr_time и prev_time будет посчитана без каких-либо проблем. В многопоточном же сценарии все не так радужно и баг дает о себе знать:
Пусть у нас есть два потока и оба вошли в заданную функцию. При этом до блокировки каждый из них получил результат функции get_current_time_ns: 0 и 1 соответственно. Пусть в блокировку входит поток у которого значение данной функции - единица(обозначу его как A), а поток с значением 0, ожидает разблокировки(обозначу его как B). В итоге, поток A при выполнении присвоит elem->prev_time единицу и даст старт потоку B, который, имея значение curr_time = 0, выполнит вычитание: 0 - 1->unsigned overflow.
@ioann_V для связи.
#multithreading #sync #cxx #hardcore
Привет. На носу Новый Год. Встречаю его на работе и в работе.
В Новом Году я обязательно выпущу серию новых статей и даже, возможно, смогу поделиться результатами на процессоре М1 от Apple. Но сначала - обязанности взятые на себя и только после - блог/все остальное. Скучно не будет. Желаю вам больше радоваться, меньше болеть, не забывать о окружающих и танцевать, много и часто.
#happy_new_year
В Новом Году я обязательно выпущу серию новых статей и даже, возможно, смогу поделиться результатами на процессоре М1 от Apple. Но сначала - обязанности взятые на себя и только после - блог/все остальное. Скучно не будет. Желаю вам больше радоваться, меньше болеть, не забывать о окружающих и танцевать, много и часто.
#happy_new_year
👍5🤨2😁1