АШ>Авторы : АШ>Александр Шаргин
АШ>Аннотация : АШ>Делегаты в CLR удобны, типобезопасны и эффективны. Последнее время на форумах RSDN часто поднимается вопрос о том, можно ли реализовать делегаты с аналогичными свойствами, оставаясь в рамках "чистого" C++. Оказывается, это вполне возможно. В этой статье я покажу, как это сделать.
Было бы неплохо всё-таки разжевать еще, как на своих аллокаторах это сделать, всё таки предоставлять читателю, скажем так, не совсем тривиальную задачу, как-то незакончено... Статья понравилась! Просто чес слова, извините за грубость, ну задолбали с этим БУСТОМ...! Да ОЧЕНЬ много, очень много кто НЕ пользует его по многим объективным причинам. Да и собсна из тех кто пользует, толком никто и незнает, как там всё устроено...
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
АШ>Авторы : АШ>Александр Шаргин
АШ>Аннотация : АШ>Делегаты в CLR удобны, типобезопасны и эффективны. Последнее время на форумах RSDN часто поднимается вопрос о том, можно ли реализовать делегаты с аналогичными свойствами, оставаясь в рамках "чистого" C++. Оказывается, это вполне возможно. В этой статье я покажу, как это сделать.
Я немного "обжегся", не посомтрев на реализацию. Используется dynamic_cast
так чтo,народ, проверьте ключ компиляции /GR. Если он не стоит — будет генериться исключение. В моем случае оно лихо ловилось, а объект из списка не удалялся.
По моей логике, чтобы это хотябы скомпилировалось, надо передать в шаблон тип класса, метод которого
передается в делеат.
NewDelegate<CMyClass, и т.д.>(pMyClass, &CMyClass::Method);
Однако, этого не требуется. Как такого вы достигли?
_>По моей логике, чтобы это хотябы скомпилировалось, надо передать в шаблон тип класса, метод которого _>передается в делеат. _>NewDelegate<CMyClass, и т.д.>(pMyClass, &CMyClass::Method);
_>Однако, этого не требуется. Как такого вы достигли?
В случае шаблона функции(NewDelegate) это не обязательно, в отличии от шаблонного класса(C_METHOD_DELEGATE). Типы будут выведены исходя из фактических типов переданных аргументов. Собственно эта функция и нужна для того, чтобы при создании объекта класса C_METHOD_DELEGATE не приходилось указывать явно его параметры.
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>В случае шаблона функции(NewDelegate) это не обязательно, в отличии от шаблонного класса(C_METHOD_DELEGATE). Типы будут выведены исходя из фактических типов переданных аргументов. Собственно эта функция и нужна для того, чтобы при создании объекта класса C_METHOD_DELEGATE не приходилось указывать явно его параметры.
Я тогда не понимаю:
NewDelegate(&obj, &CMyClass::func);
CMethodDelegate0 del(&obj, &CMyClass::func);
Почему для функции компилятор догадывается какой тип надо подставить в шаблон, а для класса нет?..
Здравствуйте, my_soul, Вы писали:
_>Я тогда не понимаю:
_>
_>NewDelegate(&obj, &CMyClass::func);
_>
_>
_>CMethodDelegate0 del(&obj, &CMyClass::func);
_>
_>Почему для функции компилятор догадывается какой тип надо подставить в шаблон, а для класса нет?..
Первая конструкция — это выражение(expression), а второй — определение объекта типа CMethodDelegate0. Как мы можем определить объект неизвестного типа ?
Кроме того, возможны ситуации с шаблонным конструктором:
template<class>
struct A
{
template<class t>
A(t){}
};
//...
A a(1); // Какой здесь тип у a ?
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>Первая конструкция — это выражение(expression), а второй — определение объекта типа CMethodDelegate0. Как мы можем определить объект неизвестного типа ?
ЮЖ>Кроме того, возможны ситуации с шаблонным конструктором:
ЮЖ>
ЮЖ>template<class>
ЮЖ>struct A
ЮЖ>{
ЮЖ> template<class t>
ЮЖ> A(t){}
ЮЖ>};
ЮЖ>//...
ЮЖ>A a(1); // Какой здесь тип у a ?
ЮЖ>
К сожалению данный код не работает корректно в VS2008:
Ваш код:
for(it = m_DelegateList.begin(); it != --m_DelegateList.end(); ++it)
static_cast<IDelegate*> (*it)->Invoke(ARGS);
Мне пришлось поменять на
if ( !m_DelegateList.empty() )
{
for(it = m_DelegateList.begin(); it != --m_DelegateList.end(); ++it)
static_cast<IDelegate*> (*it)->Invoke(ARGS);
}
так как рантайм VS2008 выбрасывает исключение нарушения границ доступа при попытке декрементировать итератор который возвращен методом end().
Best Regards. Anton.
Re: "в языке C++ операторы не наследуются (?)"
От:
Аноним
Дата:
25.11.08 18:29
Оценка:
Раз уж подняли эту тему, такой вопрос:
Насторожила фраза в статье: "Дело в том, что в языке C++ операторы не наследуются."
Попробовал на VC++2005 — наследуются. И в Стандарте не нашёл подтверждения обратному.
Буду благодарен за пояснения особенностей наследования операторов в С++.
Заранее спасибо.
PS
По ходу чтения возникла мысль: не проще ли генерировать классы на каком-либо скрипте?
А>PS А> По ходу чтения возникла мысль: не проще ли генерировать классы на каком-либо скрипте?
Кстати, не знает ли кто простой и проверенный способ в студии по описанию класса генерить операторы ==, !=, =; конструктор по умолчанию, копирования, макросы сериализации (тут ессно нуно ручками будет что то в чём то прописать), и прочий мегатонный мусор. Плюс стандартные #ifndef BLABLABLA_H_INCL__ мусор ___ #define BLABLABLA_H_INCL__ мусор ___ и #include в .cpp файле.
Чтоб вот нажал кнопку, бах и всё на месте..
Желательно было б конечно в идеале уметь обновлять все эти структуры при обновлении полей.
Или хотя бы макрос, который оформлял бы дефиницию функции в cpp по её декларации в классе в h, т.е.
.h файл
class A
{
virtual int method(const Type& .. ) const;
..
};
Здравствуйте, johny5, Вы писали:
А>>PS А>> По ходу чтения возникла мысль: не проще ли генерировать классы на каком-либо скрипте?
J>Кстати, не знает ли кто простой и проверенный способ в студии по описанию класса генерить операторы ==, !=, =; конструктор по умолчанию, копирования, макросы сериализации (тут ессно нуно ручками будет что то в чём то прописать), и прочий мегатонный мусор. Плюс стандартные #ifndef BLABLABLA_H_INCL__ мусор ___ #define BLABLABLA_H_INCL__ мусор ___ и #include в .cpp файле.
J>Чтоб вот нажал кнопку, бах и всё на месте.. J>Желательно было б конечно в идеале уметь обновлять все эти структуры при обновлении полей.
J>Или хотя бы макрос, который оформлял бы дефиницию функции в cpp по её декларации в классе в h, т.е.
J>.h файл J>
J>class A
J>{
J> virtual int method(const Type& .. ) const;
J> ..
J>};
J>
А ещё остаётся за кадром такой момент, как изменение списка во время его обхода.
Тут нужна или двойная буферизация,
vector<IDelegate*> snapshot; // вектор дешевле списка, поэтому копировать удобнее в него
snapshot.reserve(m_DelegateList.size());
snapshot.insert(m_DelegateList.begin(), m_DelegateList.end());
// далее - как с гусём :)
... или внимательность к свежедобавленным и свежеудаляемым элементам.
Свежедобавленные в конец — будут учитываться, поскольку мы проверяем фактический конец на каждой итерации цикла. (А вот если бы использовали for_each, то там запомнили бы итератор на предпоследний элемент на момент начала работы).
Свежеудалённые — болезненнее, так как может быть удалён текущий элемент, а итератор на него станет невалидным.
Не реентерабельная версия Invoke — в паре с Remove и RemoveAll может выглядеть так
Здравствуйте, johny5, Вы писали:
А>>PS А>> По ходу чтения возникла мысль: не проще ли генерировать классы на каком-либо скрипте?
J>Кстати, не знает ли кто простой и проверенный способ в студии по описанию класса генерить операторы ==, !=, =; конструктор по умолчанию, копирования, макросы сериализации (тут ессно нуно ручками будет что то в чём то прописать), и прочий мегатонный мусор. Плюс стандартные #ifndef BLABLABLA_H_INCL__ мусор ___ #define BLABLABLA_H_INCL__ мусор ___ и #include в .cpp файле.
J>Чтоб вот нажал кнопку, бах и всё на месте.. J>Желательно было б конечно в идеале уметь обновлять все эти структуры при обновлении полей.
Кстати, даже если ты будешь пользоваться своим макросом, все равно операторы лучше добавлять через Boost.Operators — там тебе придется добавить всего по одной функции на оператор, остальные она сгенерит сама, пользуясь этой функцией.
АШ>Авторы : АШ>Александр Шаргин
АШ>Аннотация : АШ>Делегаты в CLR удобны, типобезопасны и эффективны. Последнее время на форумах RSDN часто поднимается вопрос о том, можно ли реализовать делегаты с аналогичными свойствами, оставаясь в рамках "чистого" C++. Оказывается, это вполне возможно. В этой статье я покажу, как это сделать.
Возникла проблема с копированием делегатов от одного обьекта к другому:
class Object
{
C_DELEGATE* object_delegate;
Object()
{
object_delegate=new C_DELEGATE();
};
Object(const Object& x_right)
{
object_delegate=new C_DELEGATE();
*object_delegate=*(x_right.object_delegate); //Здесь скопируются указатели
};
Object& operator=(const Object& x_right)
{
*object_delegate=*(x_right.object_delegate); //Здесь скопируются указателиreturn *this;
};
C_DELEGATE* get_delegate() const
{
return object_delegate;
};
~Object()
{
delete object_delegate;
};
};
class Events
{
void Test();
};
//Тогда код:
Events events;
void main()
{
Object object2;
{
Object object1;
object1.get_delegate()->operator +=(NewDelegate(events, &Events::Test));
Object object2=object1; //Хочу скопировать объект вместе с его делегатами;
}; //Здесь object1 рушится вместе с указателями в ~C_DELEGATE, а указатели делегатов в object2 становятся не валидными
object2.get_delegate()->operator ()(); //CRASH! потому как object1 забрал в небытие указатели на делегаты с собой.
};
Понятно что в C_DELEGATE(const C_DELEGATE<TRet TEMPLATE_ARGS>& x_right) и operator== нужно копировать не указатели а делать их реальные копии, но что то не могу понять как это сделать?
Спасибо!
Re[2]: Проблема с копированием делегатов?
От:
Аноним
Дата:
31.01.09 18:23
Оценка:
Поправка в коде:
//Тогда код:
Events events;
void main()
{
Object object2;
{
Object object1;
object1.get_delegate()->operator +=(NewDelegate(events, &Events::Test));
object2=object1; //Хочу скопировать объект вместе с его делегатами;
}; //Здесь object1 рушится вместе с указателями в ~C_DELEGATE, а указатели делегатов в object2 становятся не валидными
object2.get_delegate()->operator ()(); //CRASH! потому как object1 забрал в небытие указатели на делегаты с собой.
};