Konkurs #2: rzutowanie w Pascalu

5

Wpadł mi pomysł na kolejny konkurs, zatem i ogłaszam oficjalne otwarcie drugiego ;)

Tym razem celem jest napisanie generycznej klasy o nazwie TCast ze statyczną metodą Cast, która będzie umożliwiała rzutowanie typów pomiędzy sobą.
Przykładowo kod:

Var Int: Integer;
Begin
 // TCast<TypPierwotny, TypDocelowy>.Cast(WyrażenieTypuPierwotnego)
 Int := TCast<String, Integer>.Cast('1024');
End;

Sprawi, że w zmiennej Int będzie liczba 1024.

Składnia użycia musi być identyczna, jak przedstawiona powyżej (do osiągnięcia we FPC za pomocą {$MODE DELPHI}) i muszą być możliwe następujące rzutowania:

Typ pierwotny Typ docelowy Działanie
String Integer Zamienia ciąg znaków na liczbę*
Integer String Zamienia liczbę całkowitą na ciąg znaków
Single Integer Zaokrągla liczbę**
Single String Zamienia liczbę zmiennoprzecinkową na ciąg znaków***
W razie podania innych parametrów, funkcja powinna zwracać wartość domyślną dla typu docelowego (!) - podpowiem, że takie "cuś" jest możliwe dopiero od FPC 2.7.0 (o ile dobrze pamiętam, to nawet we 2.6.3 tego nie ma) i od dłuższego czasu w Delphi (nie jestem pewien dokładnie, od której wersji).
Ostatecznie mogę przyjąć kody, które nie spełniają powyższego warunku, lecz będzie za to pewna forma "karnych punktów" (:D).

Przykładowy kod:

Writeln(TCast<String, Integer>.Cast('1024'));
Writeln(TCast<Integer, String>.Cast(2+2*2));
Writeln(TCast<Single, Integer>.Cast(10.6));
Writeln(TCast<Single, Integer>.Cast(10.4));
Writeln(TCast<Single, String>.Cast(10.5));

Powinien zwrócić:

1024
6
11
10
 1.050000000E+01

**Zasady**: 1.Nie można (jawnie) dołączać żadnego modułu. 2.Zakazane jest używanie typu `Variant`, niezależnie od sposobu i okoliczności. 3.Musi być możliwe rzutowanie za pomocą składni `TCast<typpierwotny, typdocelowy="TypDocelowy">.Cast(WyrażenieTypuPierwotnego)` 4.Rozwiązanie nie musi być przenośne. 5.Metoda `Cast` musi być statyczna i nie może być w żaden sposób overloadowana (innymi słowy: istnieć musi jedynie jedna taka metoda). 6.Program musi zwracać identyczny wynik dla przykładowego kodu, jak określony powyżej. 7.Rozwiązania proszę przysyłać mi poprzez wiadomości. 8.Konkurs kończy się za tydzień od dnia dzisiejszego, czyli trwa od 12 września 2013 roku do 19 września 2013. 9.Have fun! ;)
**Nagroda**: Tak, jak i poprzednio, do wygrania jest szacunek na całej dzielni i wszystkie te nagrody, premie oraz puchary, które za tym idą ;)
`*` w razie, gdy przekazany ciąg znaków nie jest poprawną liczbą, powinno zwrócić `0` `**` `9.8 ~ 10`, `9.5 ~ 10`, `9.4 ~ 9`, `9.0 ~ 9` i tak dalej. `***` notacja naukowa!
0

Można wiedzieć jaki powód jest tych ograniczeń
1.Variant
2.Overload;

0

1.Variant

Utrudnienie + trzeba by wtedy dołączyć moduł Variants (FPC robi to niejawnie, lecz wywala warning - nie wiem jak Delphi).

2.Overload

Ciekawe jakim cudem wykonasz takie przeładowanie:

Class Function Cast(const Value: Single): Integer; static;
Class Function Cast(const Value: Single): String; static;
0

Myślę, że przyszła pora rozstrzygnąć ten mały konkurs - tym razem jedyną osoba, która przysłała kod był @Anoxic:
http://4programmers.net/Pastebin/2421
Brawo, wygrywasz szacunek na całej dzielni i 3 kilogramy internetu! ;)

Moje rozwiązanie jest podobne, chociaż opiera się na wskaźnikach:
http://4programmers.net/Pastebin/2423

W porównaniu do poprzedniego konkursu z printf-em, tutaj aż takiej magii nie ma - wystarczy znajomość TypeInfo i banalne porównywanie TypeInfo(TypPierwotny) oraz TypeInfo(TypDocelowy), zresztą: kody chyba mówią same za siebie :D

Tym "domyślna wartość dla zmiennej" była "funkcja" o nazwie Default, do poczytania dla zainteresowanych ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1