Макрос, который принимает новый объект - PullRequest
1 голос
/ 23 сентября 2011

В моем коде есть:

#define EV( event ) SendEvent( new event );
EV( evFormat );

Но я хочу передать созданный объект в макрос EV, например:

CEvent *ev = new CEvent();
EV( ev );

Возможно ли это?Потому что нет способа изменить макрос EV.

Ответы [ 5 ]

5 голосов
/ 23 сентября 2011
#define EV( event ) SendEvent( new event );    // Can't be changed.

Макрос заставляет каждый вызов SendEvent создавать новый динамический объект.Ваша проблема не только в том, что использование макроса для этого глупо и, например, снижает читабельность вашего исходного кода.Кроме того, макрос не позволяет вам создать объект раньше, чем вызов, и что вы не можете изменить макрос;в твоих словах "нет способа изменить макрос EV".


Поэтому решение простое:

Не используйте макрос, используйте SendEventнепосредственно, и помните, чтобы не delete.

4 голосов
/ 23 сентября 2011

Способ, которым записано EV, будет генерировать новый объект при каждом вызове.Но это создание не обязательно должно относиться к объекту того же типа, что и в конечном итоге передаваемый SendEvent.Это связано с тем, что текстовая природа макросов препроцессора и более сложные выражения добавляет некоторые хитрости.Подумайте об этом:

class dummy {
private:
    static dummy* freeme;
public:
    dummy() { freeme = this; }
    static bool dofree() { delete freeme; return true; }
};
dummy* dummy::freeme;

CEvent *ev = new CEvent(this);
EV( dummy && dummy::dofree() ? ev : NULL );

Это расширится так, что вы запускаете не CEvent, а фиктивный класс ... который вы затем освобождаете, а затем все выражение оценивается какваше событие:

SendEvent( new dummy && dummy::dofree() ? ev : NULL );

(Примечание: использование?: не так хорошо, как оператор запятой, поэтому здесь есть пустая ветвь NULL, которая на самом деле никогда не происходит. Оператор запятой был бы хорош, ноМакросы препроцессора обрабатывают запятые особенно, и это один из случаев, когда его нельзя использовать. Делать его потокобезопасным оставлено в качестве упражнения для читателя.)

Чтобы сделать его "чище"но все же выразить это в терминах EV ... без явного упоминания SendEvent, вы можете создать свой собственный макрос:

#define EV2(event) EV( dummy && dummy::dofree() ? event : NULL )

... или вы можете просто использовать SendEvent, так как он кажетсяделать именно то, что вы хотите.Но где в этом веселье?; -P


ОБНОВЛЕНИЕ:

Как указывает @AlfPSteinbach, более эзотерический, но легкий способ превратить ваш new в неактивный - с размещением new:

int dummy;

CEvent *ev = new CEvent(this);
EV( (&dummy) int ? ev : NULL );

Итак, вы расширяетесь до:

SendEvent( new (&dummy) int ? ev : NULL );

Вы запускаете новое, но на этот раз не нужно беспокоиться о том, чтобы освободить результат!Потому что я не был полностью уверен, был ли это кошерный ESP.в случаях с многопоточностью я задал свой собственный вопрос:

Хорошо ли он определен / законен для размещения новых несколько раз по одному и тому же адресу?

2 голосов
/ 23 сентября 2011

Полностью выполнимо без изменения макроса. Это просто рискованно. Обратите внимание, что вам придется delete []

#include <memory>

struct CEvent {};
void SendEvent(CEvent*) {}

#define EV( event ) SendEvent( new event );

int main() {
    char *cev = new char[sizeof(CEvent)];
    CEvent* ev = (CEvent*)cev;

    EV( (ev)CEvent );

    ev->~CEvent();
    delete [] cev;
}

http://ideone.com/

1 голос
/ 23 сентября 2011

У вас может быть утечка памяти, если SendEvent не управляет ею изнутри, что-то вроде

void SendEvent(const Event *ev) {
     doSendEvent(ev);
     delete ev;
}

Кроме того, вы пробовали это, оно должно работать

EV(CEvent)

Если нет, вы можете переопределить оператор new для класса CEvent, чтобы вышеуказанный вызов работал.

Но ваш вопрос действительно необычный. Вы уверены, что там идете по правильному пути?

1 голос
/ 23 сентября 2011

Если вы не можете изменить макрос EV, это невозможно. Разве вы не можете создать свой собственный макрос, который вместо этого SendEvent( event );?

Обновление: Будет ли возможность #undef оригинального макроса и дать свое собственное определение? Предполагая, что вы хотите только новое поведение, вы можете сделать

#undef EV
#define EV( event ) SendEvent( event );

но теперь вам нужно будет заменить исходный тип вызова на EV( new event ).

...