- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
#define CREATE_EVENT_LISTENER(_elname, arg1_type, arg1_name) \
class _elname : public EventListener \
{ \
private: \
class IContainer \
{ \
public: \
virtual void Call(arg1_type arg1_name) = 0; \
virtual ~IContainer() {} \
}; \
\
class FunctionContainer : public IContainer \
{ \
private: \
typedef void(*__CallbackPtr)(arg1_type); \
public: \
FunctionContainer(__CallbackPtr fn) \
{ \
this->fn = fn; \
} \
\
virtual void Call(arg1_type arg1_name) \
{ \
fn(arg1_name); \
} \
\
private: \
__CallbackPtr fn; \
}; \
\
template<class T, class Q> \
class MethodContainer : public IContainer \
{ \
public: \
MethodContainer(T method, Q _this) \
{ \
this->method = method; \
this->_this = _this; \
} \
\
virtual void Call(arg1_type arg1_name ) \
{ \
(_this->*method)(arg1_name); \
} \
\
private: \
T method; \
Q _this; \
}; \
public: \
typedef void(*__FN_CALLBACK)(arg1_type); \
\
_elname(__FN_CALLBACK fn) \
{ \
this->container = new FunctionContainer(fn); \
} \
\
template <class T, class Q> \
_elname(T method, Q _this) \
{ \
this->container = new MethodContainer<T, Q>(method, _this); \
} \
\
void Call(arg1_type arg1_name) \
{ \
container->Call(arg1_name); \
} \
\
virtual ~_elname() \
{ \
delete this->container; \
} \
private: \
IContainer* container; \
}; \
#define CREATE_EVENT(_ename, _elname, arg1_type, arg1_name) \
class _ename : public Event \
{ \
public: \
void AddListener(_elname* listener) \
{ \
Event::AddListener(listener); \
} \
\
void Handle(arg1_type arg1_name) \
{ \
for (size_t i = 0; i < this->listeners.size(); i++) \
{ \
((_elname*)listeners[i])->Call(arg1_name); \
} \
} \
\
void RemoveListener(_elname* listener) \
{ \
Event::RemoveListener(listener); \
} \
\
}; \
Я когда то это написал. Думал, это хорошая идея...
Полный файл: https://github.com/arhyme/CPP_EVENTS/blob/master/Event.h
Antervis 18.07.2016 14:41 # −2
kurwa-nextgen 18.07.2016 15:00 # −2
Antervis 18.07.2016 15:45 # 0
bakagaijin 18.07.2016 14:56 # 0
kurwa-nextgen 18.07.2016 15:04 # −1
Это такая обфускация?
Antervis 18.07.2016 15:46 # −2
codemonkey 18.07.2016 15:51 # −2
Dummy00001 18.07.2016 16:33 # −2
не гони на табы.
они не виноваты в том что некоторые идиоты (ака: подавляющее большинство девелоперов) до 8 считать не умеют.
ЗЫ копи-пасти в VIM. потом ":set ts=4"
Tsiklonyashka 18.07.2016 15:22 # +2
codemonkey 18.07.2016 15:50 # +3
(3.1) Each identifier that contains a double underscore __ or begins with an underscore followed by an
uppercase letter is reserved to the implementation for any use.
(3.2) Each identifier that begins with an underscore is reserved to the implementation for use as a name in
the global namespace
Good job, fag.
Antervis 18.07.2016 16:00 # 0
codemonkey 18.07.2016 16:05 # 0
Antervis 18.07.2016 16:14 # 0
Soul_re@ver 18.07.2016 16:17 # 0
Antervis 18.07.2016 16:46 # −1
Soul_re@ver 18.07.2016 17:10 # 0
Функция А имеет два разных определения в разных TU: А1 и А2.
А1 заинлайнилась в месте использования, а А2 компилер решил не инлайнить.
Линкер увидел что А — inline и взял первое попавшееся определение — А1.
Теперь код, который хотел вызвать А2 вызывает А1. И заметить это непросто.
Antervis 18.07.2016 17:40 # −1
(потестил на mingw. inline-определение перекрыло не инлайн-объявление, что по идее странно, но в остальном сработало предсказуемо)
Soul_re@ver 18.07.2016 17:51 # +2
Dummy00001 18.07.2016 17:53 # −1
статик инлайн.
обычные инлайн функции они просто обычные функции (с хинтом компилеру "плиз заинлайнь"), и если у тебя есть два определения в разных TU, то линкер пожалуется.
Antervis 18.07.2016 17:58 # −1
Soul_re@ver 18.07.2016 18:03 # 0
Dummy00001 18.07.2016 18:04 # −1
https://gcc.gnu.org/onlinedocs/gcc/Inline.html
PS из доки, единственная разница между inline vs always_inline это что последнее даже в дебуге будет заинлайнено.
kurwa-nextgen 18.07.2016 15:59 # 0
> 8 апреля
Только не говори, что с тех пор ты повзрослел, набрался опыта, все переосмыслил и сейчас бы уже такое не сделал.
Dummy00001 18.07.2016 16:35 # +2
wvxvw 18.07.2016 18:28 # −3
Это нормально? Т.е. такой объект можно будет как-то создать снаружи?
Soul_re@ver 18.07.2016 18:35 # 0
wvxvw 18.07.2016 18:37 # −3
Soul_re@ver 18.07.2016 18:42 # +1
using my_int = int;
assert(is_same<my_int, int>); //Всегда true, в любую функцию ждущую my_int можно засунуть int
Утиная типизация — в шаблонах.
wvxvw 18.07.2016 18:48 # −3
Может немножко крови попортить. Я думал, что только в сишке так.
Dummy00001 18.07.2016 19:03 # −1
с другой стороны, для того что бы твой пример работал, придется долго потрахатся, потому что как никрути, как долго секунды/минуты конвертятся в инты/из интов, строгой типизации у тебя ни как не получится. я в прошлом подобное делал с enum'ами и знакомые делали со структурами/классами - те же яйца: надо часто конвертить туда сюда, потому что иначе арифметика не работает. а потом появляются еще и ошибки типа `seconds_t S = 42; minutes_t M = minutes_t(to_int(S) + 1);` и начинают опускаться руки, потому что понимаешь что как ни крути, от ошибок не спасешься. (и даже в какой-то степени хуже получается, потому что меньше ожидаешь ошибок в таких местах, т.к. типа type-safe обертками пользуешься.)
bormand 18.07.2016 19:12 # −1
Дык назови этот метод не to_int() а to_int_in_seconds() или seconds_as_int(). И говно сразу всплывёт на поверхность. Один хуй он нужен чуть менее чем никогда, поди только в реально низкоуровневых методах, поэтому длинное название никому не повредит...
З.Ы. А у нас вот тайпсейф обёртки неплохо код почистили от странных кастов, умножений и делений... И от раздумий "а в чём же эта хуйня измеряется", заодно.
> seconds_t S = 42
g:explicit
Dummy00001 18.07.2016 19:32 # −1
я просто хотел подчеркнуть что это не панацея.
абсолютные обёртки - (seconds_as_int() - мама, роди меня назад) - жутко не удобно использовать (сам не писал, но arbitrary precision кода в жабе насмотрелся). и чем дырявее/удобнее обертка, тем меньше гарантий она предоставляет.
bormand 18.07.2016 19:43 # −1
Ты так часто скармливаешь кишки этих обёрток системным апишкам и сторонним либам? Ну вот в этих местах это будет отличным напоминанием о том, в чём измеряется их параметр.
А explicit конструктор - это страховка от злоебучих SetTimer(event, TimerRelative, 380), в которых потом хуй поймёшь, то ли автор реально хотел 38 микросекунд, то ли всё-таки 380, но забыл про особенность ёбаного EFI'шного таймера, и надо перелопатить кучу спецификаций, чтобы выяснить сколько там реально должно стоять...
roman-kashitsyn 18.07.2016 23:09 # 0
sleep(int timeout)
Ладно в сишке средств минимум, но уж в плюсцах-то всё есть, чтобы сделать нормально.
У нас в кодбазе повсюду std::chrono::{seconds,milliseconds}, полёт нормальный, касты в инт ни разу не видел.
Soul_re@ver 18.07.2016 23:16 # 0
bormand 18.07.2016 23:50 # 0
Лень гуглить, пора няшек смотреть и спать...
Soul_re@ver 19.07.2016 00:23 # +1
bormand 18.07.2016 23:21 # +1
http://wiki.phoenix.com/wiki/index.php/EFI_BOOT_SERVICES#SetTimer.28.29
Тогда, я думаю, тебе понравится вот эта функция :3
roman-kashitsyn 19.07.2016 10:09 # +1
Да, тут ещё лучше. И из сигнатуры сходу не понятно, спим for или until, и единицы измерения кучерявые.
Dummy00001 18.07.2016 23:25 # 0
> // минутка саморекламы
> https://habrahabr.ru/post/198568/
да делали мы уже все это - уже 15 лет назад.
в прошлом (сечас не пробовал) грабли были что эти прокладки добавляли код. по старой памяти, тестовый код без прокладки был на ~10% меньше чем код с прокладкой.
bormand 18.07.2016 23:31 # 0
Ты про бинарный? Ну в дебаге прилично дуют, да, в основном из-за всяких ассёртов внутри операторов...
Dummy00001 19.07.2016 00:40 # 0
за годы много чего поменялось - может нынешнии компилеры умнее при выкидывании лишнего кода.
bormand 19.07.2016 18:42 # 0
Ну акцессоры и конструкторы же в хедере были описаны, я надеюсь? Х.з., у меня сейчас всё выкидывает ;)
Dummy00001 19.07.2016 14:09 # +1
с прокладкой, или без прокладки (typedef int), GCC 4.8.2 генерит идентичный код, почти байт в байт.
так что можно пользоватся не напрягаясь.
Soul_re@ver 19.07.2016 14:19 # +1
bormand 19.07.2016 18:43 # 0
Dummy00001 19.07.2016 13:37 # 0
к слову. я пропустил что твой IdOf другим целям служит.
почти с тем же эффектом, вместо `template <> class IdOf {}` я в прошлом пользовался enum'ами: С++ разные энумы сравнивать/присваивать не даёт. другими словами, вместо `typedef IdOf<Gadget> GadgetId;` я делал просто `enum GadgetId {}`. (потестировал: на сравнение разных энумов, g++ бросает ворнинг, а не ошибку.)
основное отличие в том что энумы в числа конвертируются без вопросов - без класса прокладки этого не запретить.
roman-kashitsyn 19.07.2016 14:26 # 0
В старых плюсах нельзя выбрать underlying type у енума. Так что нужно как минимум ещё воткнуть в енум большую константу, чтобы компилятор взял достаточно широкий тип.
Кстати, там в комментах предлагали решение с enum class-ами, весьма годное, если юзать C++11.
Dummy00001 19.07.2016 14:55 # 0
и в числа они без явного приведения тоже не конвертируются. гугл говорит что преднамеренно. прогресс.
ЗЫ но все равно пидары: не добавили строковое представления для членов энумов...
bormand 19.07.2016 18:44 # 0
А каст числа в енум случаем не UB, если в енуме не было такого числа?
bormand 19.07.2016 19:06 # 0
An expression of arithmetic or enumeration type can be converted to an enumeration type explicitly. The value is unchanged if it is in the range of enumeration values of the enumeration type; otherwise the resulting enumeration value is unspecified.
З.Ы. А, in range, т.е. походу от минимального до максимального... Т.е. всё ок, если добавить в енум 0 и максимум.
Odin 03.11.2018 17:08 # 0
Это Тор нужен чуть менее, чем никогда, а я нужен! У него молоко на губах не обсохло!
Soul_re@ver 18.07.2016 19:14 # 0
Soul_re@ver 18.07.2016 19:16 # +1
Dummy00001 18.07.2016 19:27 # 0
в том же примере что с минутами/секундами - делашь нормальных человеческий `struct myTime { int hours, mins, secs; /* + overloaded ops */ }` и все опять же работает. во многих случаях нежелание делать специализированые типы (и желание что то генерик/юниверсал сделать) и ведет к говнокодам.
Antervis 19.07.2016 04:55 # 0
Dummy00001 19.07.2016 09:59 # 0
guest 19.07.2016 17:29 # 0
Psionic 25.07.2016 01:42 # +2