Читайте FastDelegate от RSDN, я когда-то (100700 лет назад) 1 раз его дописал под свои нужды, и по универсальности ещё ни один
boost не догоняет....
юзабилити простое, хочь бинди глобал функцию, хочь мембер класса, не важно, хочь статик мембер, хочь, переменную,
короче, кто как допишет. (в любых нотациях, cdecl / stdcall и т.д.)
и по красивше... обьявил UnknownDelegate ud где-то.
есть у него всякие stl вкусности типо empty, clear и т.п.
void func() {}
написал ud.bind( func );
или там в теле класса (если память не подкачала)
ud.bind( this, func );
и позвал ud(); или там ud.call(); короче под любой стиль можно адаптировать :D
Я ещё на них как-то писал типо безопасный var arg, т.е. vprintf :D
Самое приятное (не помню писал сам или было),
что в одном делегате можно менять функции, ребиндить например с глобал на мембер :)
В общем, концепция очень приятная и портабельная.
Lolmen
Жесть... И всё ради 2 ассемблерных строчек:)
З.Ы.
Чуть мозг не сломал, пока вкурил как это работает
0xdeadc0de
>Мне нужен не совсем делегат, а нечто, что могло бы сохранить в себе обьект, его функцию, её параметры, и быть "прозрачно"-одинаковым и не зависеть от используемого обьекта, его функции и параметров этой функции.
Велосипедисты омг. Чем тебе не подходит function<void(void)> и каррирование где надо с помощью bind ?
Гопник Хаскель
И я о том же :(
Можно как-то так:
class IDelegate { public: virtual void call() = 0; virtual ~IDelegate( ) {} }; template <typename Class, typename RT> IDelegate *makeDelegate( Class *obj, RT ( Class::*method)( )) { class CurrentDelegate : public IDelegate { Class *obj_; RT ( Class::*method_)( ); public: CurrentDelegate( Class *anObj, RT ( Class::*aMethod)( )) : obj_( anObj), method_( aMethod) {} virtual void call( ) { ( obj_->*method_)( ); } }; return new CurrentDelegate( obj, method); } template <typename Class, typename RT, typename T1> IDelegate *makeDelegate( Class *obj, RT ( Class::*method)( T1), T1 arg1) { class CurrentDelegate : public IDelegate { Class *obj_; RT ( Class::*method_)( T1); T1 arg1_; public: CurrentDelegate( Class *anObj, RT ( Class::*aMethod)( T1), T1 anArg1) : obj_( anObj), method_( aMethod), arg1_( anArg1) {} virtual void call( ) { ( obj_->*method_)( arg1_); } }; return new CurrentDelegate( obj, method, arg1); }
И так далее для каждого допустимого количества аргументов (Если тебе мало шаблонной магии, попробуй, например, Boost.Preprocessor). Способа без повторения придумать не удалось, есть сильные подозрения, что это невозможно.
Использование:
struct Test { void foo(char c) { cout << "Test::bar('" << c << "')" << endl; } }; int main( int argc, char **argv) { Test test; IDelegate *del = makeDelegate( &test, &Test::foo, '!'); del->call( ); delete del; return 0; }
0xdeadc0de
Чем Вы занимаетесь? Расскажите. Интересно.
0xdeadc0de
> Мне нужен не совсем делегат, а нечто, что могло бы сохранить в себе обьект, его
> функцию, её параметры, и быть "прозрачно"-одинаковым и не зависеть от
> используемого обьекта, его функции и параметров этой функции.
Посмотри списки типов. А ещё лучше прочти первую книжку Александреску.
Делаешь контейнер, которому передаешь список типов, и который будет хранить данные.
По желанию - класс, переводящий тип функции в список типов параметров, для удобства.
Потом делаешь класс, который вызывает функцию, и передает ей параметры.
Другими словами получится что-то вроде этого:
class tmy_class { public: int my_func(int value0, float value1, double value2) { std::cout << value0 << " " << value1 << " " << value2 << std::endl; return 4; }; };
tmy_class myclass; hell::functor<int(int, float, double)> f0; //в разделе инициализации f0.bind( &tmy_class::my_func, &myclass); f0.set( 1, 2.0f, 3.0); //там, где надо вызвать f0( ); std::cout << f0.GetResult( ) << std::endl;
выдает:
1 2 3 4
Я себе подобную штуку лет 5 назад сделал, до сих пор доволен и использую)
Гопник Хаскель
>>Велосипедисты омг.
Несколько причин. Я плохо знаю шаблоны, и это один из вариантов разобраться. Системные велосипеды слишком повышенной жирности и предназначены для немного других целей. Тупо хочется иметь формат записи, удобный и логичный лично для меня. Желание сделать свою версию, лишенную лишних аллокаций/проверок/ненужных_возможностей.
AxMeT
Хочу попробовать сделать Lock-free scaleable мультитрединговую систему. Во всех статьях, которые читал, везде предлагается разбивать либо:
- 1. каждая подсистема использует свой поток
- 2. каждая подсистема выполняет свою работу на потоке через планировщик
- 3. система работает "однопоточно", но разбиваются на потоки примитивы вычислений (работа с матрицами/массивами, работа с числами в цикле и etc) через openmp/tbb
Я хочу попробовать вариант, похожий на 2, но не "система делает работу на веделенной ей потоке", а "система генерирует множество микроработ, которые планировщиком запускаются на доступных потоках". Грубо говоря, есть EntityManager, который каждый кадр обновляет 3000 сущностей. По моим задумкам этот менеджер сгенерирует 3000 Job'ов и отдаст их планировщику, который построит граф зависимостей и вызовов, и сделает очередь работ, которой не будет требоваться локи мьютексов, семафоров, критсекций и прочего.
Плюс всё должно очень хорошо скалиться на кол-во доступных потоков (колво cpu-ядер)
Данный велосипед, придумываемый в треде, призван реализовать класс, который будет хранить в себе обьект и его работу.
Примерно так.
Dusk
Первая книга, это какая? "Современное проектирование на C++", раздел обобщенные функторы?
Ок, гляну.
0xdeadc0de
> Первая книга, это какая? "Современное проектирование на C++"
Она самая, только смотреть лучше сначала. Там функторы не айс, главное со списками типов научиться работать, вот их посмотри.
На их основе можно много всего полезного сделать)
0xdeadc0de
Т.е. каждая работа (job) будет самодостаточна и не будет обращения к глобальным переменным (к тем же контейнерам). Это получается нечто на подобие макрокоманд? Можете описать тривиальные работы на примерах?
Опять же если не изменяются глобальные состояния нужно будет обратные операции производить по сохранению состояния. Поправьте если я не понял сути.
На практике пока не применял многопоточное программирование. Но тема интересная, сам склоняюсь к OpenMP.
PS от сути темы отклонился, извиняюсь.
Тема в архиве.