C++ Макро замены vs. шаблоны в туториалах DirectX

Вопросы по языкам программирования Си и С++.
Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение Admiralisimys » 04.04.2011 (Пн) 22:59

Доброго времени суток.

Изучая вводный пример по Direct2D, наткнулся на интересную конструкцию
Код: Выделить всё
template<class Interface>
inline void SafeRelease(
    Interface **ppInterfaceToRelease
    )
{
    if (*ppInterfaceToRelease != NULL)
    {
        (*ppInterfaceToRelease)->Release();

        (*ppInterfaceToRelease) = NULL;
    }
}

и её последующее применение
Код: Выделить всё
    SafeRelease(&m_pRenderTarget);
    SafeRelease(&m_pLightSlateGrayBrush);
    SafeRelease(&m_pCornflowerBlueBrush);


Данный код призван свести рутину по освобождению COM объектов до одной строчки.
Ничего удивительного: их дело предложить, моё - сделать по своему :)
Код: Выделить всё
   if(m_pRenderTarget)
      m_pRenderTarget -> Release ();
   if(m_pLightSlateGrayBrush)
      m_pLightSlateGrayBrush -> Release ();
   if(m_pLinearGradientBrush)
      m_pLinearGradientBrush -> Release ();

   m_pRenderTarget = NULL;
   m_pLightSlateGrayBrush = NULL;
   m_pLinearGradientBrush = NULL;


Однако попался ещё один пример: распечатка кода BGMusic.cpp
Это пример-исходник с одной из предыдущих версий DirectX (кажется 8й версии, в документе копирайт МикроСофт от 2000 года), в нём предлагался макро подстановочный вариант.
Код: Выделить всё
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL;} }


Казалось бы, новый вариант предложил бы компактность (имеется ввиду бинарная, то есть та которая будет сказываться на конечный размер файла. В исходнике в обоих случая будет одна строчка кода), если б не просьба про inline, которая компактность заменяет быстродействием, так как функция будет вставлена во все места, где её будет вызывать.
По ключевому слову template и так получается генерация функции для каждого нового типа, так если б не inline хоть компактность единого существования функции для переменных одного типа.

И в чём собственно преимущество нового подхода в туториале?

p.s.
Если копнуть по литературе, скажем к версии 3й DirectX, то там выступают против макро варианта, ратуют за вариант который выбрал я.

Обычно после вызова Release я присваиваю указателю значение NULL, чтобы облегчить поиск программных ошибок — например, попыток использования недопустимого указателя на интерфейс. Если вы любите макросы (лично я их не люблю), то всегда можете создать макрос RELEASE, который вызывает функцию Release и присваивает указателю значение NULL:
#define RELEASE(p) ((р)->Release(); (p) = NULL;)
Найджел Томпсон - Программирование трехмерной графики для Windows 95

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение Хакер » 05.04.2011 (Вт) 0:49

Admiralisimys писал(а):Казалось бы, новый вариант предложил бы компактность (имеется ввиду бинарная, то есть та которая будет сказываться на конечный размер файла. В исходнике в обоих случая будет одна строчка кода), если б не просьба про inline, которая компактность заменяет быстродействием, так как функция будет вставлена во все места, где её будет вызывать.
По ключевому слову template и так получается генерация функции для каждого нового типа, так если б не inline хоть компактность единого существования функции для переменных одного типа.

Не переварил. Существующие ошибки восприятия настолько впечатаны в вопрос, что с позиции отсутствия этих ошибок вопросительная сущность вопроса вообще перестаёт существовать.

Что касается сипипишного варианта: крайне непонятно, зачем вообще понадобилось привлекать шаблоны. Что касается бинарной компактности, оба варианта дадут одинаковых выходной код.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

BV
Thinker
Thinker
Аватара пользователя
 
Сообщения: 3987
Зарегистрирован: 12.09.2004 (Вс) 0:55
Откуда: Молдавия, г. Кишинёв

Re: C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение BV » 05.04.2011 (Вт) 8:12

Admiralisimys писал(а):Казалось бы, новый вариант предложил бы компактность (имеется ввиду бинарная, то есть та которая будет сказываться на конечный размер файла. В исходнике в обоих случая будет одна строчка кода), если б не просьба про inline, которая компактность заменяет быстродействием, так как функция будет вставлена во все места, где её будет вызывать

Ну, ты удивишься, но макрос препроцессор не разворачивает в функцию по месту определения, а подставляет тело во все места вызова макроса.
Хакер писал(а):крайне непонятно, зачем вообще понадобилось привлекать шаблоны

Возможно, "на будущее", для возможности как-то по особому подходить к освобождению некоторых интерфейсов
const char *out = "|*0>78-,+<|"; size_t cc = char_traits<char>::length(out);
for (size_t i=0;i<cc;i++){cout<<static_cast<char>((out[i]^89));}cout<<endl;

NashRus
Постоялец
Постоялец
 
Сообщения: 388
Зарегистрирован: 18.03.2006 (Сб) 1:16

Re: C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение NashRus » 05.04.2011 (Вт) 9:09

Admiralisimys писал(а):И в чём собственно преимущество нового подхода в туториале?

Более строгая типизация?

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Re: C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение Admiralisimys » 05.04.2011 (Вт) 15:00

Всем спасибо за ответы.

Хакер попробую описать, на чём основывается моё восприятие.
inline – просьба к компилятору вставить не адрес самой функции по месту вызова, если последняя, по его мнению, не слишком громоздка, а функцию целиком. Есть согласие с этим тезисом?
template – собственно ключевое слово по созданию шаблонной функции/класса. Второй раз функция не будет генерироваться (с подстановкой реального типа) если указанный тип уже был задействован. А значит существовать в одном экземпляре и в одном месте в бинарнике. Так?

То бишь
Код: Выделить всё
template <typename Type>
/*inline*/void SortArray(Type array){/*...*/};
//...
int iMass[4], iMass2[4];
long lMass[8], lMass2[8];

SortArray(iMass);
SortArray(iMass2);

SortArray(lMass);
SortArray(lMass2);

Генерируется две функции SortArray, по одному экземпляру на тип.
Если добавить inline, будет так же сгенерировано две функции, но в двух экземплярах, для каждого вызова последней.

Соответственно если убрать inline, то шаблонный вариант будет отличаться от варианта с макро заменой, на бинарном уровне.
В теории.
На практике, почему-то генерируется одинаковый ASM код (cl /Fa), не исключено что для простых типов отрабатывает оптимизатор. Вспомнить хоть спор ++k vs. k++. На простых типах (int, long) меняется регистр, но для составных (вроде Вектора) уже видно превосходство ++k в скорости.

Если всё же это не так, прошу указать, в чём именно ошибки восприятия. Спасибо.

BV как работают макро подстановки в курсе, ведь привёл ещё и вариант который выбрал я. Единственное при макро замене будет обнуление сразу, а не лишь погодя.

Кстати, обратили внимание, что в былые времена в макросе SAFE, не проверяли на нуль указатель, перед вызовом Release?

NashRus вполне возможно, что решили избавится от проблем присущих макросам.
Взять ещё туже по строчную отладку, макросы не годятся, а заменять одну строчку освобождения на три (как в моём вариант) не захотели, вот и решили взять лучше из двух миров и стали использовать шаблонную функцию.

BV
Thinker
Thinker
Аватара пользователя
 
Сообщения: 3987
Зарегистрирован: 12.09.2004 (Вс) 0:55
Откуда: Молдавия, г. Кишинёв

Re: C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение BV » 05.04.2011 (Вт) 17:42

Admiralisimys писал(а):BV как работают макро подстановки в курсе, ведь привёл ещё и вариант который выбрал я.

Тогда зачем ты упомянул про скорость? Никакой выгоды скорости по отношению к макросам тут нет
Admiralisimys писал(а):Кстати, обратили внимание, что в былые времена в макросе SAFE, не проверяли на нуль указатель, перед вызовом Release?

Это в какие былые?
const char *out = "|*0>78-,+<|"; size_t cc = char_traits<char>::length(out);
for (size_t i=0;i<cc;i++){cout<<static_cast<char>((out[i]^89));}cout<<endl;

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Re: C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение Admiralisimys » 05.04.2011 (Вт) 18:10

BV скорость упомянул в другой связи.
Admiralisimys писал(а):... просьба про inline, которая компактность заменяет быстродействием,

То есть не сравнивая с define вариантом, а между обычной функцией(компактность) и inline(скорость вызова).

Извеняюсь за не внятно написанное в первом посте.

Времена DirectX 3й версии и Windows 95.
Admiralisimys писал(а):p.s.
Если копнуть по литературе, скажем к версии 3й DirectX, ...

... то всегда можете создать макрос RELEASE, который вызывает функцию Release и присваивает указателю значение NULL:
#define RELEASE(p) ((р)->Release(); (p) = NULL;)
Найджел Томпсон - Программирование трехмерной графики для Windows 95

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение iGrok » 05.04.2011 (Вт) 20:17

Admiralisimys писал(а):Времена DirectX 3й версии и Windows 95.

Вот поэтому более поздние варианты и называются уже SAFE_RELEASE, а не просто RELEASE. :)
label:
cli
jmp label

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение Хакер » 06.04.2011 (Ср) 0:25

Admiralisimys писал(а):inline – просьба к компилятору вставить не адрес самой функции по месту вызова, если последняя, по его мнению, не слишком громоздка, а функцию целиком. Есть согласие с этим тезисом?

Просьба, ох... Это предписание вызов функции заменить на код функции. Причём замена осуществляется на промежуточном уровне — не на уровне исходника, но и не на уровне выходного кода.

Admiralisimys писал(а):template – собственно ключевое слово по созданию шаблонной функции/класса. Второй раз функция не будет генерироваться (с подстановкой реального типа) если указанный тип уже был задействован. А значит существовать в одном экземпляре и в одном месте в бинарнике. Так?

Эмм... не понял твоей мысли. Вернее, наверное ты не понял смысл шаблонов.

Admiralisimys писал(а):Генерируется две функции SortArray, по одному экземпляру на тип.

Компилятор не будет генерировать две функции с одинаковым кодом, а здесь именно этот случай. Так что по делу будет скорее всего одна функция.
Admiralisimys писал(а):Если добавить inline, будет так же сгенерировано две функции, но в двух экземплярах, для каждого вызова последней.

Если добавить inline — никаких функций вообще сгенерировано не будет, будет выполнено 4 подстновки блоков промежуточных инструкций.

Admiralisimys писал(а):NashRus вполне возможно, что решили избавится от проблем присущих макросам.
Взять ещё туже по строчную отладку, макросы не годятся, а заменять одну строчку освобождения на три (как в моём вариант) не захотели, вот и решили взять лучше из двух миров и стали использовать шаблонную функцию.

Допустим, но зачем взяли шаблонную функцию, а не просто функцию?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

BV
Thinker
Thinker
Аватара пользователя
 
Сообщения: 3987
Зарегистрирован: 12.09.2004 (Вс) 0:55
Откуда: Молдавия, г. Кишинёв

Re: C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение BV » 06.04.2011 (Ср) 9:18

Хакер писал(а):Допустим, но зачем взяли шаблонную функцию, а не просто функцию?

Как я сказал выше, что бы, например, в перспективе иметь возможность применить typeid.
const char *out = "|*0>78-,+<|"; size_t cc = char_traits<char>::length(out);
for (size_t i=0;i<cc;i++){cout<<static_cast<char>((out[i]^89));}cout<<endl;

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение Хакер » 06.04.2011 (Ср) 9:19

BV писал(а):Как я сказал выше, что бы, например, в перспективе иметь возможность применить typeid.

Подробнее пожалуйста. Для чего это может быть нужно?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Re: C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение Admiralisimys » 07.04.2011 (Чт) 13:29

Хакер что это за промежуточный уровень?
В ассемблерном листинге, выданном cl по запросу через ключ Fa, никаких изменений не происходит при добавлении inline перед именем функции. В обоих случаях значится две функции и четыре вызова, на два на каждую.

Смысл шаблонов заключается в том, что бы функцию (для данного примера - сортировки) достаточно написать один раз, дабы использовать с разными типами данных. Это в теории.
На практике же, если не ограничиваться int и long, как в данном примере, единожды написанная функция может оказаться не панацеей для всех типов данных, и нужно будет осуществлять ещё специализацию шаблонов.

P.S.
Код С++
Код: Выделить всё
template <typename Type>
inline void SortArray(Type array)
{
   array[0] = 0;//для примера, дабы функция делала хотя бы что-то
}

void main()
{
   int iMass[4], iMass2[4];
   long lMass[8], lMass2[8];

   SortArray(iMass);
   SortArray(iMass2);

   SortArray(lMass);
   SortArray(lMass2);
}

Листинг cl /Fa
Код: Выделить всё
; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01

   TITLE   main.cpp
   .686P
   .XMM
   include listing.inc
   .model   flat

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

PUBLIC   ??$SortArray@PAJ@@YAXPAJ@Z         ; SortArray<long *>
PUBLIC   ??$SortArray@PAH@@YAXPAH@Z         ; SortArray<int *>
PUBLIC   _main
; Function compile flags: /Odtp
_TEXT   SEGMENT
_iMass$ = -96                  ; size = 16
_lMass$ = -80                  ; size = 32
_iMass2$ = -48                  ; size = 16
_lMass2$ = -32                  ; size = 32
_main   PROC
; File main.cpp
; Line 9
   push   ebp
   mov   ebp, esp
   sub   esp, 96               ; 00000060H
; Line 13
   lea   eax, DWORD PTR _iMass$[ebp]
   push   eax
   call   ??$SortArray@PAH@@YAXPAH@Z      ; SortArray<int *>
   add   esp, 4
; Line 14
   lea   ecx, DWORD PTR _iMass2$[ebp]
   push   ecx
   call   ??$SortArray@PAH@@YAXPAH@Z      ; SortArray<int *>
   add   esp, 4
; Line 16
   lea   edx, DWORD PTR _lMass$[ebp]
   push   edx
   call   ??$SortArray@PAJ@@YAXPAJ@Z      ; SortArray<long *>
   add   esp, 4
; Line 17
   lea   eax, DWORD PTR _lMass2$[ebp]
   push   eax
   call   ??$SortArray@PAJ@@YAXPAJ@Z      ; SortArray<long *>
   add   esp, 4
; Line 18
   xor   eax, eax
   mov   esp, ebp
   pop   ebp
   ret   0
_main   ENDP
; Function compile flags: /Odtp
_TEXT   ENDS
;   COMDAT ??$SortArray@PAH@@YAXPAH@Z
_TEXT   SEGMENT
_array$ = 8                  ; size = 4
??$SortArray@PAH@@YAXPAH@Z PROC            ; SortArray<int *>, COMDAT
; Line 4
   push   ebp
   mov   ebp, esp
; Line 5
   mov   eax, DWORD PTR _array$[ebp]
   mov   DWORD PTR [eax], 0
; Line 6
   pop   ebp
   ret   0
??$SortArray@PAH@@YAXPAH@Z ENDP            ; SortArray<int *>
; Function compile flags: /Odtp
_TEXT   ENDS
;   COMDAT ??$SortArray@PAJ@@YAXPAJ@Z
_TEXT   SEGMENT
_array$ = 8                  ; size = 4
??$SortArray@PAJ@@YAXPAJ@Z PROC            ; SortArray<long *>, COMDAT
; Line 4
   push   ebp
   mov   ebp, esp
; Line 5
   mov   eax, DWORD PTR _array$[ebp]
   mov   DWORD PTR [eax], 0
; Line 6
   pop   ebp
   ret   0
??$SortArray@PAJ@@YAXPAJ@Z ENDP            ; SortArray<long *>
_TEXT   ENDS
END

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение Хакер » 07.04.2011 (Чт) 13:33

Admiralisimys писал(а):Хакер что это за промежуточный уровень?

Компилятор же не разом исходный текст в машинный код гонит.

Admiralisimys писал(а):В ассемблерном листинге, выданном cl по запросу через ключ Fa, никаких изменений не происходит при добавлении inline перед именем функции. В обоих случаях значится две функции и четыре вызова, на два на каждую.

Стоит попробовать __inline и потвикать процесс некоторыми доп. ключами.

Admiralisimys писал(а):Смысл шаблонов заключается в том, что бы функцию, для данного примере сортировки, достаточно написать один раз, дабы использовать с разными типами данных.

Речь шла о вызове метода Release у COM-объектов.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Re: C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение Admiralisimys » 07.04.2011 (Чт) 13:45

Хакер писал(а):Речь шла о вызове метода Release у COM-объектов.

Это был ответ на
Хакер писал(а):Вернее, наверное ты не понял смысл шаблонов.


Насколько знаю, директивы начинающиеся с двойной нижней линии, специализированны в рамках конкретного компилятора, а позицию inline рассматривает стандарт языка. Так что ж это получается, если хочется писать стандартизированный код, то в реализации он будет игнорирован, если не использовать оптимизацию под конкретный компилятор?
Заменил на __inline, никаких изменений не последовало. Что за доп. ключи могут отвечать за поведения на inline? Вроде нашёл http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx
И там кстати говориться
The __inline keyword is equivalent to inline.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: C++ Макро замены vs. шаблоны в туториалах DirectX

Сообщение Хакер » 07.04.2011 (Чт) 14:00

Admiralisimys писал(а):Что за доп. ключи могут отвечать за поведения на inline?

Код: Выделить всё
/Ob<n> inline expansion (default n=0)


Совсем недавно я замечал разницу между inline и __inline в игнорировании предписании компилятором. Правда язык был Си, но компилятор — cl (да, BV, cl).
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.


Вернуться в С/С++

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0

    TopList  
cron