std::complex<double> не расширяется inline
От: Аноним  
Дата: 22.01.08 21:23
Оценка:
Собственно проблема следующая:

Есть тестовый код:

#include <complex>

int _main(int argc, _TCHAR* argv[])
{
std::complex<double> c1(argc, 0), c2(argc, argc);
std::complex<double> c3 = c1 + c2;

return (int)c3.real();
}


После компиляции имеем следующее (листинг из встроенного дизассемблера VisualStudio)

std::complex<double> c1(argc, 0), c2(argc, argc);
003A1009  fild        dword ptr [argc] 
 std::complex<double> c3 = c1 + c2;
003A100C  lea         eax,[esp] 
003A100F  push        eax  
003A1010  lea         ecx,[esp+14h] 
003A1014  fst         qword ptr [esp+14h] 
003A1018  push        ecx  
003A1019  fldz             
003A101B  lea         edx,[esp+28h] 
003A101F  fstp        qword ptr [esp+20h] 
003A1023  push        edx  
003A1024  fst         qword ptr [esp+0Ch] 
003A1028  fstp        qword ptr [esp+14h] 
003A102C  call        dword ptr [__imp_std::operator+<double> (3A2038h)] 

 return (int)c3.real();
003A1032  fld         qword ptr [esp+2Ch] 
003A1036  add         esp,0Ch 
003A1039  call        _ftol2_sse (3A1840h) 
}
003A103E  mov         esp,ebp 
003A1040  pop         ebp  
003A1041  ret


Достаточно заменить std::complex<double> на std::complex<int> и сгенерированный код сильно изменится:

 std::complex<int> c1(argc, 0), c2(argc, argc);
 std::complex<int> c3 = c1 + c2;
00F41006  mov         eax,dword ptr [argc] 
00F41009  add         eax,eax 

 return (int)c3.real();
}
00F4100B  mov         esp,ebp 
00F4100D  pop         ebp  
00F4100E  ret


Собственно именно такой он и должен быть!

Фишка в том, что оператор сложения не подставляется в код, а происходит вызов в CRT библиотеку. Хитрые индусы или кто-то там сделали явные инстанциации шаблона std::complex для типов float, double и long double. Кроме того, они не поленились понавставлять атрибутов __declspec(dllimport) в эти инстанциации.

Самое смешное в том, что MSDN явно говорит про совместное использование ключевых слов inline и dllimport (при этом, если возможно, идет подстановка тела функции, а если невозможно, например берется адрес функции, то вызывается копия из DLL). Идиотизм усугубляется тем, что тестовые DLL и EXE, которые его использует, со своей собственной функцией, работает именно так, как написано в MSDN — то есть правильно!

Но класс для комплексных чисел из стандартной библиотеки отказывается расширятся наотрез! Может кто-то сталкивался с подобным?

Кстати, сия проблема присутствует только если CRT прилинкована как DLL. При статической компоновке все нормально, собственно там макрос стоит который убирает атрибут dllimport в этом случае (а также если мы собираем с ключем /clr:pure). Все пришедшие на ум ключи компилятора были перепробованы. (К слову среда VisualStudio 2008, но насколько я помню и под 2005 будет тоже самое.)

Я все еще надеюсь что я чего-то НИАСИЛИЛ, и у этой проблемы есть решение.


01.02.08 21:13: Перенесено модератором из 'C/C++. Прикладные вопросы' — Кодт
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.