Форум: "Прочее";
Текущий архив: 2007.12.09;
Скачать: [xml.tar.bz2];
ВнизОбъясните пожалуйста дельфисту, что такое шаблоны в Си? Найти похожие ветки
← →
Mystic © (2007-11-01 16:37) [80]> Есть мнение что это промежуточный асемблер…
Это мне показал cordbg.exe. Скомпилировано в релизе.
← →
clickmaker © (2007-11-01 16:37) [81]
> что это промежуточный асемблер
а что это (сорри за серость)?
← →
homm © (2007-11-01 16:41) [82]> [81] clickmaker © (01.11.07 16:37)
> а что это (сорри за серость)?
Асемблерные команды, понимаемые jit компилятором. Промежуточное представление кпрограммы, до того, как она оттранслируется во время выполнеия в машинные кода.
← →
clickmaker © (2007-11-01 16:42) [83]
> Асемблерные команды, понимаемые jit компилятором
видимо jit туповат все-таки... если банальный if ему так надо разжевать :)
← →
Mystic © (2007-11-01 16:59) [84]> Асемблерные команды, понимаемые jit компилятором.
Эти ассемблерные команды, пониамемые JIT-компилятором, называются иструкциями CIL. Там есть такие команды, как box, callvirt, castclass, newobj, newarr и т. д. Тут же нативный AMD64 ассемблер. Я не пробовал, как это скомпилируется в 32-битной Windows, может там оптимизатор получше. Но под 64 битами результаты устрашающе угнетающие.
К тому же как можно упростить этот "промежуточный" код? По большому счету никак, он и так оптимизирован на уровне ассемблерных инструкций. Оптимизировать его надо было уровнями выше.
← →
clickmaker © (2007-11-01 17:01) [85]
> ; if (Color == System.Drawing.Color.Black)
> 0000008d lea rcx,[rsp+20h]
судя по всему, там какая-то предварительная работа... только вот, хрен знает, зачем
ну не может один if в такую простыню развернуться. Хоть на 32-бит, хоть на 64, хоть на Марсе...
← →
Mystic © (2007-11-01 17:24) [86]> clickmaker © (01.11.07 17:01) [85]
Второй if разворачивается в аналогичную конструкцию (32 бита). Может у кого-то получится это сделать более оптимально?--- C:\Mu\Labs\cs\test1\Program.cs ---------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
namespace test1
{
class Program
{
static void Main(string[] args)
{
System.Drawing.Color Color = System.Drawing.Color.Black;
00000000 push ebp
00000001 mov ebp,esp
00000003 push edi
00000004 push esi
00000005 sub esp,64h
00000008 mov esi,ecx
0000000a lea edi,[ebp-6Ch]
0000000d mov ecx,18h
00000012 xor eax,eax
00000014 rep stos dword ptr es:[edi]
00000016 mov ecx,esi
00000018 mov dword ptr [ebp-0Ch],ecx
0000001b cmp dword ptr ds:[0092885Ch],0
00000022 je 00000029
00000024 call 79421156
00000029 lea ecx,[ebp-2Ch]
0000002c call 7A191508
00000031 lea edi,[ebp-1Ch]
00000034 lea esi,[ebp-2Ch]
00000037 movs dword ptr es:[edi],dword ptr [esi]
00000038 movs dword ptr es:[edi],dword ptr [esi]
00000039 movs dword ptr es:[edi],dword ptr [esi]
0000003a movs dword ptr es:[edi],dword ptr [esi]
if (Color != System.Drawing.Color.Black)
0000003b lea edi,[ebp-3Ch]
0000003e lea esi,[ebp-1Ch]
00000041 movs dword ptr es:[edi],dword ptr [esi]
00000042 movs dword ptr es:[edi],dword ptr [esi]
00000043 movs dword ptr es:[edi],dword ptr [esi]
00000044 movs dword ptr es:[edi],dword ptr [esi]
00000045 lea ecx,[ebp-4Ch]
00000048 call 7A191508
0000004d lea eax,[ebp-3Ch]
00000050 push dword ptr [eax+0Ch]
00000053 push dword ptr [eax+8]
00000056 push dword ptr [eax+4]
00000059 push dword ptr [eax]
0000005b lea eax,[ebp-4Ch]
0000005e push dword ptr [eax+0Ch]
00000061 push dword ptr [eax+8]
00000064 push dword ptr [eax+4]
00000067 push dword ptr [eax]
00000069 call 7A18C808
0000006e mov esi,eax
00000070 test esi,esi
00000072 je 0000007F
System.Console.WriteLine("Catastrophic execution");
00000074 mov ecx,dword ptr ds:[0228307Ch]
0000007a call 78747F3C
if (Color == System.Drawing.Color.White)
0000007f lea edi,[ebp-5Ch]
00000082 lea esi,[ebp-1Ch]
00000085 movs dword ptr es:[edi],dword ptr [esi]
00000086 movs dword ptr es:[edi],dword ptr [esi]
00000087 movs dword ptr es:[edi],dword ptr [esi]
00000088 movs dword ptr es:[edi],dword ptr [esi]
00000089 lea ecx,[ebp-6Ch]
0000008c call 7A18A2B4
00000091 lea eax,[ebp-5Ch]
00000094 push dword ptr [eax+0Ch]
00000097 push dword ptr [eax+8]
0000009a push dword ptr [eax+4]
0000009d push dword ptr [eax]
0000009f lea eax,[ebp-6Ch]
000000a2 push dword ptr [eax+0Ch]
000000a5 push dword ptr [eax+8]
000000a8 push dword ptr [eax+4]
000000ab push dword ptr [eax]
000000ad call 7A18A424
000000b2 mov esi,eax
000000b4 test esi,esi
000000b6 je 000000C3
System.Console.WriteLine("Catastrophic execution");
000000b8 mov ecx,dword ptr ds:[0228307Ch]
000000be call 78747F3C
}
000000c3 nop
000000c4 lea esp,[ebp-8]
000000c7 pop esi
000000c8 pop edi
000000c9 pop ebp
000000ca ret
← →
Mystic © (2007-11-01 18:02) [87]Хорошо, протестировал сей момент:
Исходник C#, test1.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace test1
{
class Program
{
static void Main(string[] args)
{
System.DateTime begin = System.DateTime.Now;
for (int i=0; i<50000000; ++i)
{
System.Drawing.Color Color = System.Drawing.Color.Black;
if (Color != System.Drawing.Color.Black)
System.Console.WriteLine("Catastrophic execution");
if (Color == System.Drawing.Color.White)
System.Console.WriteLine("Catastrophic execution");
}
System.DateTime end = System.DateTime.Now;
Console.WriteLine(end - begin);
}
}
}
Исходник C++, test2.cpp
#include <iostream>
#include "windows.h"
namespace System
{
namespace Drawing
{
class Color
{
private:
int value;
Color(const int _value): value(_value) {}
public:
Color(const Color& color): value(color.value) {}
static const Color White;
static const Color Black;
friend bool operator == (const Color& color1, const Color& color2) { return color1.value == color2.value; }
friend bool operator != (const Color& color1, const Color& color2) { return color1.value != color2.value; }
};
const Color Color::White(0x00FFFFFF);
const Color Color::Black(0x00000000);
}
}
int main()
{
LARGE_INTEGER begin, end, f;
QueryPerformanceFrequency(&f);
double frequency = static_cast<double>(f.QuadPart);
QueryPerformanceCounter(&begin);
for (int i=0; i<50000000; ++i)
{
System::Drawing::Color Color = System::Drawing::Color::Black;
if (Color != System::Drawing::Color::Black)
std::cout << "Catastrophic execution" << std::endl;
if (Color == System::Drawing::Color::White)
std::cout << "Catastrophic execution" << std::endl;
}
QueryPerformanceCounter(&end);
std::cout << (end.QuadPart - begin.QuadPart) / frequency << std::endl;
return 0;
}
Результаты:
C:\Mu\Labs\cs\test1\bin\Release>test1.exe
00:00:05.7343750
C:\Mu\Labs\cs\test2\Release>test2.exe
0.0569969
Итого, разница примерно в 100 раз :)
← →
Mystic © (2007-11-01 18:03) [88]Что видно по ассемблерному коду C++:
#include <iostream>
namespace System
{
namespace Drawing
{
class Color
{
private:
int value;
Color(const int _value): value(_value) {}
public:
Color(const Color& color): value(color.value) {}
static const Color White;
static const Color Black;
friend bool operator == (const Color& color1, const Color& color2) { return color1.value == color2.value; }
friend bool operator != (const Color& color1, const Color& color2) { return color1.value != color2.value; }
};
const Color Color::White(0x00FFFFFF);
const Color Color::Black(0x00000000);
}
}
int main()
{
System::Drawing::Color Color = System::Drawing::Color::Black;
00401000 mov eax,dword ptr [System::Drawing::Color::Black (403374h)]
if (Color != System::Drawing::Color::Black)
std::cout << "Catastrophic execution" << std::endl;
if (Color == System::Drawing::Color::White)
00401005 cmp eax,dword ptr [System::Drawing::Color::White (40301Ch)]
0040100B jne main+2Ah (40102Ah)
std::cout << "Catastrophic execution" << std::endl;
0040100D mov eax,dword ptr [__imp_std::endl (402038h)]
00401012 mov ecx,dword ptr [__imp_std::cout (402054h)]
00401018 push eax
00401019 push ecx
0040101A call std::operator<<<std::char_traits<char> > (401160h)
0040101F add esp,4
00401022 mov ecx,eax
00401024 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402040h)]
return 0;
0040102A xor eax,eax
}
0040102C ret
← →
homm © (2007-11-01 18:09) [89]> [87] Mystic © (01.11.07 18:02)
> Итого, разница примерно в 100 раз :)
Жесть :)
Где там госпадин Alkid ?
← →
Amoeba © (2007-11-01 18:21) [90]
> vpbar © (01.11.07 14:05) [29]
>
> Alkid © (01.11.07 13:58) [27]
> Для таких случаев можно симулировать :)
> http://www.delphikingdom.com/asp/viewitem.asp?catalogid=744
> и ww.delphikingdom.com/asp/viewitem.asp?catalogid=453 есть
> статья получше. Но ссылку не помню.
>
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=891
← →
Alkid © (2007-11-01 18:23) [91]
> Жесть :)
> Где там госпадин Alkid ?
Я тут. :)
Если заметите, здесь не чисто вычислительная задача, а задача связанная с вводом-выводом :)
А они там действительно могут подтормаживать.
← →
Джо © (2007-11-01 18:31) [92]К сожалению, большинство *реальных* программ не занимаются только вычислением. Я готов признать, что для вычисления a := sqrt(b*sin(c)/123) в .Net генерится хороший, грамотный машинный код, врял ли, конечно, он быстрее кода, скомпилированного из C++, но все же он будет *достаточно быстр*.
Но в *реальных* программах, как правило, встречаются сравнения, условные переходы (господин Mystic уже показал, во что они компилятся) и (ужас!) операции ввода-вывода.
Так что, надо признать, что все эти тесты скорости программ под .Net никакого *практического* применения не имеют.
← →
Джо © (2007-11-01 18:33) [93]Собственно, это даже не нужно доказывать теоретически, ибо видно и «на глазок» — все программы на Дотнет, которые я видел, тормозили.
То же самое с Джавой. Можно сколько угодно рассуждать о тестах скорости, о быстроте выполнения, но, опять же, «на глазок» — они тормозят и все тут :)
← →
Mystic © (2007-11-01 18:40) [94]
> Если заметите, здесь не чисто вычислительная задача, а задача
> связанная с вводом-выводом :)
Ввод-вывод не выполняется :) Единственный вывод этих программ вначале и в конце, так что это вычислительная задача :)
Вообще-то примеры тут несколько некорректны, потому что указывают на наэффективность реализации System.Drawing.Color. Если сляпать похожий класс самому, то разница будет примерно в 20 раз:C:\Mu\Labs\cs\test1\bin\Release>test1.exe
00:00:00.9843750
Нет, если алгоритмический код выполнять в процедурном стиле, все мелкие функции инлайнить ручками, то мы и в C# приблизимся к результату C++. Что и показывают тесты. Скажем, если в этом примере не использовать класс MyColor, а вместо использовать int, медоды заменить статическими вызовами, а самые мелкие из них инлайнить руками... Но для этого надо специально извращаться, код в результате будет негибкий :) А для тестов, чтобы показать могучесть JIT-компилятора---самый раз
Программа:
using System;
using System.Collections.Generic;
using System.Text;
namespace test1
{
struct MyColor
{
private int value;
private MyColor(int _value)
{
value = _value;
}
static public bool operator == (MyColor color1, MyColor color2)
{
return color1.value == color2.value;
}
static public bool operator !=(MyColor color1, MyColor color2)
{
return color1.value != color2.value;
}
static public MyColor White
{
get
{
/* avoid boxing/unboxing operations in case of return new MyColor(0x00FFFFFF) */
MyColor retVal;
retVal.value = 0x00FFFFFF;
return retVal;
}
}
static public MyColor Black
{
get
{
MyColor retVal;
retVal.value = 0x00000000;
return retVal;
}
}
}
class Program
{
static void Main(string[] args)
{
/* JIT compilation of MyColor"s methods */
MyColor t1 = MyColor.White;
MyColor t2 = MyColor.Black;
if ((t1==t2) == (t1 != t2))
System.Console.WriteLine("Catastrophic execution");
System.DateTime begin = System.DateTime.Now;
for (int i=0; i<50000000; ++i)
{
MyColor Color = MyColor.Black;
if (Color != MyColor.Black)
System.Console.WriteLine("Catastrophic execution");
if (Color == MyColor.White)
System.Console.WriteLine("Catastrophic execution");
}
System.DateTime end = System.DateTime.Now;
Console.WriteLine(end - begin);
}
}
}
← →
isasa © (2007-11-01 19:29) [95]Джо © (01.11.07 18:33) [93]
Собственно, это даже не нужно доказывать теоретически, ибо видно и «на глазок» — все программы на Дотнет, которые я видел, тормозили.
То же самое с Джавой. Можно сколько угодно рассуждать о тестах скорости, о быстроте выполнения, но, опять же, «на глазок» — они тормозят и все тут :)
В основном тормозят из-за криворукости писателей, которые во время "тяжелых" операций пытаются визуализировать ход их выполнения.
Пример, использование TMemo для показа добавления большого числа строк(т.е. TMemo.Add(...) внутри большого цикла).
Про Java молчу, там и без этого (при Resize окна) видно, что графический движок оставляет желать лучшего ...
← →
wicked © (2007-11-01 21:12) [96]> Джо © (01.11.07 18:33) [93]
> Собственно, это даже не нужно доказывать теоретически, ибо
> видно и «на глазок» — все программы на Дотнет, которые я
> видел, тормозили.
> То же самое с Джавой. Можно сколько угодно рассуждать о
> тестах скорости, о быстроте выполнения, но, опять же, «на
> глазок» — они тормозят и все тут :)
да.... для определения "тормознутости" можно глянуть Paint.NET (дотнет) или Eclipse (джава)...
> isasa © (01.11.07 19:29) [95]
>
> Про Java молчу, там и без этого (при Resize окна) видно,
> что графический движок оставляет желать лучшего ...
там много движков - AWT, Swing, SWT - который из них?
← →
Джо © (2007-11-01 21:43) [97]> [96] wicked © (01.11.07 21:12)
> да.... для определения "тормознутости" можно глянуть Paint.NET
> (дотнет) или Eclipse (джава)...
Оба продукта тормознутые.
← →
@!!ex © (2007-11-01 22:17) [98]У Paint.NET даже установщик тормозит...
Хотя софтина приятная.
← →
Джо © (2007-11-01 22:44) [99]Но, видимо, рекордсмен тормозов — это ДжБилдер, не ко сну будь упомянут :)
← →
Efir (2007-11-02 00:34) [100]Ну почему же, Paint.Net вполне быстро работает. Последние версии неплохо оптимизированы.
← →
Mystic © (2007-11-05 18:12) [101]Никто не спорит, что на C# можно писать оптимизированные с учетом производительности программы. Но... отсутствие inline функций заставляет реализовывать inline-ы руками (Copy + Paste). Далее, экземпляры классов (и структур) помещаются не в регистрах, а в памяти (чтобы можно было взять адрес при передаче по ссылке). Ну и необходимо знать не только как писать оптимальные программы, но и ньюансы .NET (что получится в CLI инструкциях, как эти инструкции потом переведутся в ассемблер, boxing/unboxing).
← →
oxffff © (2007-11-05 19:22) [102]
> Mystic © (05.11.07 18:12) [101]
> Далее, экземпляры классов (и структур) помещаются не в регистрах,
> а в памяти (чтобы можно было взять адрес при передаче по
> ссылке).
А что в других языках структуры в регистрах хранятся?
:)
Теперь что касаемо inline.
Method Implementation Flags
The nonterminal symbol <impl> in the method definition form denotes the implementation flags of the method (the ImplFlags entry of a Method record).
The implementation flags are
..............
• noinlining (0x0008). The runtime is not allowed to inline the method—that is, to
replace the method call with explicit insertion of the method’s IL code.
Даже возможно IL Inlining in High-Level Languages с помощью спецсредств.
← →
Юрий Зотов © (2007-11-05 19:53) [103]> Alkid © (01.11.07 13:58) [27]
Хотите, прямо здесь, за 5 минут напишу на Delphi контейнер, абсолютно универсальный, абсолютно типобезопасный и без всяких шаблонов?
← →
Сусл © (2007-11-05 19:56) [104]
> Хотите, прямо здесь, за 5 минут напишу на Delphi контейнер,
> абсолютно универсальный, абсолютно типобезопасный и без
> всяких шаблонов?
я хочу. очень.
только - проверка типов в compile-time, а не в runtime.
← →
Юрий Зотов © (2007-11-05 20:10) [105]> Сусл © (05.11.07 19:56) [104]
Тоже можно, но уже не за 5 минут, конечно. Эксперт IDE с BeforeCompile способен проверить что угодно.
← →
Alkid © (2007-11-05 20:26) [106]
> Хотите, прямо здесь, за 5 минут напишу на Delphi контейнер,
> абсолютно универсальный, абсолютно типобезопасный и без
> всяких шаблонов?
Очень хочу, но именно Compile-time проверку типов :)
Касательно IDE-эксперта - это хотелось поподробнее. Меня терзают смутные сомнения, что это будет тот "шаблонатор", только не в компилятор встроенный, а "сбоку" прикрученный.
← →
Mystic © (2007-11-05 20:52) [107]> А что в других языках структуры в регистрах хранятся?
> :)
Если помещаются в регистр---почему нет? Если я объявлюclass A { private: int x; }
, то если это возможно, то локальные переменные обычно размещаются в регистрах.
А вот в .NET 64 я не так давно видел такую картину: по стандарту stdcall переменные передаются в регистрах (их там дофига от R8 до R15). Поэтому вызов функции сводился к тому, что значения из памяти копировались в регистры. Потом происходил вызов функции. а затем переменные из памяти копировались в стек, где и положено быть локальным переменным :)
> Теперь что касаемо inline.
И как это легко использовать?
> Меня терзают смутные сомнения, что это будет тот "шаблонатор",
> только не в компилятор встроенный, а "сбоку" прикрученный.
А какая, собственно говоря, разница? Чем Вас так не устраивает прикрученность сбоку? LEX + YACC удобная библиотека для лексического и синтаксического анализа, но ее тоже можно назвать прикрученной сбоку, потому как что в C++, что в Delphi она генерируют код. Написать утилиту, которая принимает на вход файл описаний и генерирует нужные контейнеры это дело одного дня.
← →
Юрий Зотов © (2007-11-05 20:53) [108]> Alkid © (05.11.07 20:26) [106]
ОК, значит будем считать, что все прекрасно понимают, что проверка типа в run-time - абсолютно не проблема:
type
TSafeContainer = class(...)
protected
class procedure TMyContainer.GetItemClass: TClass; virtual; abstract;
class procedure CheckItemClass(Item: TObject; Strict: boolean); dynamic;
public
procedure Add(Item: TObject);
procedure Insert(Item: TObject; Index: Integer);
procedure Append(Item: TObject);
// и т.п.
end;
// И вызываем этот метод из Add, Insert, Append и т.п.
class procedure TSafeContainer.CheckItemClass(Item: TObject; Strict: boolean);
begin
if ... then
raise ...
end;
class procedure TSafeContainerDescendantExample.GetItemClass: TClass;
begin
Result := TНужный_класс
end;
Тперь что касается Compile-time: задача, конечно, намного сложнее, но в принципе, решаема. В IDE можно (и даже несложно) вживить собственный эксперт, метод которого будет автоматически вызываться средой перед компиляцией проекта. В этом методе, вообще говоря, можно сделать что угодно, хоть собственный препроцессор наваять.
← →
oxffff © (2007-11-05 21:09) [109]
> Mystic © (05.11.07 20:52) [107]
> > А что в других языках структуры в регистрах хранятся?
> > :)
>
> Если помещаются в регистр---почему нет? Если я объявлю
> class A { private: int x; }, то если это возможно, то локальные
> переменные обычно размещаются в регистрах.
>
> А вот в .NET 64 я не так давно видел такую картину: по стандарту
> stdcall переменные передаются в регистрах (их там дофига
> от R8 до R15). Поэтому вызов функции сводился к тому, что
> значения из памяти копировались в регистры. Потом происходил
> вызов функции. а затем переменные из памяти копировались
> в стек, где и положено быть локальным переменным :)
Что касаемо classA, то его нельзя разместить в регистре по причине того, что экземпляр класса содерживат еще дополнительные служебный поля, кроме поля X. Вы наверное имели ввиду value type.
Которые могут быть размещены в регистре при размере value type в int.
В .NET нет понятия регистров. Но есть понятие evaluation stack, который естественно при компиляции в native код транслируется на набор регистров и слоты стека потока.
:)
Что касаемо передачи stdcall, то все передается через стек.
← →
Mystic © (2007-11-05 21:33) [110]> Которые могут быть размещены в регистре при размере value
> type в int.
Может быть и могут, я не видел.
В .NET нет понятия регистров. Но есть понятие evaluation stack, который естественно при компиляции в native код транслируется на набор регистров и слоты стека потока.
Это понятно. Я говорю о том, как JIT в реализации .NET на платформе x86 использует регистры.
Что касаемо передачи stdcall, то все передается через стек.
Это справедливо для 32-х битной среде. В 64-х битной среде STDCALL == FASTCALL.
← →
Mystic © (2007-11-05 21:38) [111]Тут описано соглашения вызова функций для AMD64:
http://blogs.msdn.com/oldnewthing/archive/2004/01/14/58579.aspx
Других пока что нет :)
← →
Сусл © (2007-11-05 21:39) [112]
> Юрий Зотов © (05.11.07 20:10) [105]
> Тоже можно, но уже не за 5 минут, конечно. Эксперт IDE с
> BeforeCompile способен проверить что угодно.
Знаешь, Юра, "способен" и "проворачивает" две огромные разницы.
Ты и за месяц это не напиешь. Могу даже объяснить почему. Тебе придется написать нефиговый парсер. Причем повторить те же ошибки, которые есть в парсере самого дельфи :) Это титаническая работа.
К тому же, Юра, позволь заметить следующую вещь. К сожалению в дельфи нет доступа к распарсеному тексту. Ну то есть - либо исх. код, либо готовый бинирник. В java есть возможность обращаться а байт-коду, который, конечно, намного легче для использования, нежели исх. код. Я недавно читал статью про статическое тестирование (напомню, что традиционно под термином понимается выявление ошибок на основе изучения кода без его выполнения). В частности там были обсуждены некоторые приблуды к eclipse, которые позволяют выполнять статическое тестирование программ на java на основе расширяемых шаблонов. Ну так вот. Все инструменты опираются на использование байт-кода. Сам понимаешь, что сделать твой эксперт в таком случае на порядок проще.
Резюм, я бы не говорил, что сделать такой эксперт ТЕБЕ вообще возможно (имеется в виду экономическая целесообразность). Почему я выделил ТЕБЕ? А потому, что ты, хоть и способный программист, но не имеешь доступа к внутреннему дереву компиляции кода на Delphi. Я уверен, что эксперты от самого CodeGear имеет естественно недокументированный доступ к такому дереву. Иначе объяснить относительно качественную работу экспертов рефакторинга объяснить сложно.
← →
Mystic © (2007-11-05 21:50) [113]> Знаешь, Юра, "способен" и "проворачивает" две огромные разницы.
> Ты и за месяц это не напиешь.
Думаю, что ты не понял основной идеи :) Смотри, есть некоторый файл, который содержит нечто следующее:
OUTPUT myutils.pas
USES MyUnit1, MyUnit2, MyUnit2
LIST TMyObj1 ITEM IS CLASS TMyClass1
DICTIONARY TMyObj2 KEY IS Integer VALUE IS RECORD TRecord1
Эту же информацию можно задать и в GUI эксперта. На основании этой информации генерируется исходникuses myutils;
interface
uses MyUnit1, MyUnit2, MyUnit2;
type
TMyObj1 = class
private
...................
public
constructor Create;
destructor Destroy; override;
procedure Add(Value: TMyObj1);
property Items[I: Integer]: TMyObj1 read GetItem write SetItem default;
end;
...............
implementation
......................
end.
Этот исходник включается в проект, автоматически обновляется и используется :)
← →
Черный Шаман (2007-11-05 21:58) [114]
> Alkid © (01.11.07 13:58) [27]
Там есть ClassName и Published свойства которые можно достать в рантайм. Все отлично и без шаблонов можно сделать с использованием особенностей RTTI, причем все отлично читается и понимается потом.
← →
Черный Шаман (2007-11-05 22:14) [115]
> homm © (01.11.07 14:57) [46]
>
> > [41] Alkid © (01.11.07 14:50)
> > Видишь ли, это сейчас для всего, кроме embedded систем
> и
> > мобильный платформ, на которых я ни разу не специализируюсь,
>
> > уже ОЧЕНЬ МАЛЕНЬКИЙ недостаток.
>
> Ага, уже любой пенсионер на свою пенсию и из любой деревни
> может выкачать из инета 30 метров. ;)
На компакте со всеми программами использующими .NET всегда лежит сама среда. А 700 МБ или 4.7 Гб(DVD) для всех хватит. DVD-RW(хороший Asus/Nec) стоит 37$, вполне бюджетно для пенсионера.
← →
Alkid © (2007-11-05 22:20) [116]
> А какая, собственно говоря, разница? Чем Вас так не устраивает
> прикрученность сбоку? LEX + YACC удобная библиотека для
> лексического и синтаксического анализа, но ее тоже можно
> назвать прикрученной сбоку, потому как что в C++, что в
> Delphi она генерируют код. Написать утилиту, которая принимает
> на вход файл описаний и генерирует нужные контейнеры это
> дело одного дня.
Да я и не спорю, просто тогда это и получаются те самые "шаблоны в Дельфи", о ненужности которых постоянно твердят некоторые участники форума.
← →
Alkid © (2007-11-05 22:21) [117]
> ОК, значит будем считать, что все прекрасно понимают, что
> проверка типа в run-time - абсолютно не проблема:
Гм. А где метод Get? Он-то в данном случае наиболее интересен. Точнее тип его возвращаемого значения. И еще точнее - надо ли каждый раз при взятии элемента из контейнера делать приведение типов от более общего к частному?
← →
Alkid © (2007-11-05 22:24) [118]
> Там есть ClassName и Published свойства которые можно достать
> в рантайм. Все отлично и без шаблонов можно сделать с использованием
> особенностей RTTI, причем все отлично читается и понимается
> потом.
Тем, что
1. Этот контейнер не ловит во время компиляции попыток положить в него объект не того класса. Он их ловит только во время исполнения.
2. Использование RTTI снижает производительность операции добавления элемента в контейнер.
3. Взятие элемента из контейнера будет требовать явно прописанного в коде приведения типов, что будет замусоривать исходники.
Это не фатальные недостатки, в конце концов люди жили раньше с одним TObjectList`ом и выкручивались (равно как и с ArrayList в .NET до появления дженериков).
← →
Юрий Зотов © (2007-11-05 22:43) [119]> Сусл © (05.11.07 21:39) [112]
Дима, я не то что за месяц, я и за 3 месяца вряд ли это напишу. И никто не говорил, что это простая задача. Но решаемая.
Эксперту для проверки валидности класса Item"ов нужен доступ:
а). К классам уже загруженных пакетов (причем эти классы ему заранее известны - это класс абстрактного контейнера и его потомки). Такой доступ у эксперта есть, поскольку он сам - часть среды.
б). К исходникам проекта. Такой доступ у него тоже есть (через интерфейсы BorlandIDEServices).
Все. Ни какому дереву компиляции доступ не требуется. Да, придется писать парсер. Да, непростой. Да, многое, помимо парсера тоже не будет очень уж просто. Ну и что? Разве это означает принципиальную невозможность? Не означает.
И при чем тут какая-то там экономическая целесообразность? Зачем притягивать за уши аргументы, не имеющие к сабжу никакого отношения?
Уж не говоря о способе [113], когда исходник юнита генерится "на лету".
← →
oxffff © (2007-11-05 23:30) [120]
> Юрий Зотов © (05.11.07 22:43) [119]
> > Сусл © (05.11.07 21:39) [112]
>
> Дима, я не то что за месяц, я и за 3 месяца вряд ли это
> напишу. И никто не говорил, что это простая задача. Но решаемая.
>
Есть готовые реализации парсера Delphi. Причем с исходниками.
DGrok?
Страницы: 1 2 3 4 5 вся ветка
Форум: "Прочее";
Текущий архив: 2007.12.09;
Скачать: [xml.tar.bz2];
Память: 0.75 MB
Время: 0.052 c