Lidi dělají divné věci. Například spouští Linux v Excelu. Využít je emulátor RISC-V mini-rv32ima sestavený jako knihovna DLL, která je volaná z makra VBA (Visual Basic for Applications).
Revolut nabídne neomezený mobilní tarif za 12,50 eur (312 Kč). Aktuálně startuje ve Velké Británii a Německu.
Společnost Amazon miliardáře Jeffa Bezose vypustila na oběžnou dráhu první várku družic svého projektu Kuiper, který má z vesmíru poskytovat vysokorychlostní internetové připojení po celém světě a snažit se konkurovat nyní dominantnímu Starlinku nejbohatšího muže planety Elona Muska.
Poslední aktualizací začal model GPT-4o uživatelům příliš podlézat. OpenAI jej tak vrátila k předchozí verzi.
Google Chrome 136 byl prohlášen za stabilní. Nejnovější stabilní verze 136.0.7103.59 přináší řadu novinek z hlediska uživatelů i vývojářů. Podrobný přehled v poznámkách k vydání. Opraveno bylo 8 bezpečnostních chyb. Vylepšeny byly také nástroje pro vývojáře.
Homebrew (Wikipedie), správce balíčků pro macOS a od verze 2.0.0 také pro Linux, byl vydán ve verzi 4.5.0. Na stránce Homebrew Formulae lze procházet seznamem balíčků. K dispozici jsou také různé statistiky.
Byl vydán Mozilla Firefox 138.0. Přehled novinek v poznámkách k vydání a poznámkách k vydání pro vývojáře. Řešeny jsou rovněž bezpečnostní chyby. Nový Firefox 138 je již k dispozici také na Flathubu a Snapcraftu.
Šestnáctý ročník ne-konference jOpenSpace se koná 3. – 5. října 2025 v Hotelu Antoň v Telči. Pro účast je potřeba vyplnit registrační formulář. Ne-konference neznamená, že se organizátorům nechce připravovat program, ale naopak dává prostor všem pozvaným, aby si program sami složili z toho nejzajímavějšího, čím se v poslední době zabývají nebo co je oslovilo. Obsah, který vytvářejí všichni účastníci, se skládá z desetiminutových
… více »Richard Stallman přednáší ve středu 7. května od 16:30 na Technické univerzitě v Liberci o vlivu technologií na svobodu. Přednáška je určená jak odborné tak laické veřejnosti.
Rád by jsem vám představil další projekt, na kterém jsem začal pracovat přibližně před šesti lety a od té doby jsem jej několikrát využil při implementaci řešení některých úloh se kterými jsem se setkal. Program se jmenuje cont (od slova container) a reprezentuje preprocesor rozšířeného jazyka C/C++, který nahrazuje značky umístěné ve zdrojovém kódu, kódem implementujícím abstraktní datové typy popsané těmito značkami.
Při vývoji software jsem si všiml, že významnou část času strávím zapisováním kódu pro manipulaci s objekty, který se příliš netýká implementovaných algoritmů. Mám na mysli inicializaci datových struktur, jejich uvolňování, kopírování objektů a podobně. Často se v rámci takového kódu mění pouze datové typy se kterými pracuje, zatímco jejich základní struktura zůstává zachována. Na základě výše uvedeného jsem se rozhodl implementovat program, který by mi umožnil psát pouze kód, nad kterým je nutné přemýšlet.
Zdrojové soubory programu zapsaného v jazyce C/C++ obsahují značky určené pro zpracování generátorem kontejnerů. Každý zdrojový .cc
soubor je zpracován programem cont, který ve zdrojovém souboru rozpozná jemu určené značky, a na základě informací získaných z těchto značek generuje výsledný zdrojový soubor. Vygenerovaný zdrojový soubor je připraven pro zkompilování kompilátorem jazyka C/C++.
Program cont požaduje minimálně jeden argument příkazové řádky, který se odkazuje na zdrojový .cc
soubor. Následující argumenty programu identifikují adresáře, ve kterých budou hledány hlavičkové soubory použité pro generování výsledného souboru. Výsledný zdrojový soubor je zapisován na standardní výstup programu cont.
cont <source-file> <inc-dir> <inc-dir> ... > <target-file>
Je vhodné umístit zpracování zdrojových souborů programem cont do souboru Makefile
, který se stará o překlad projektu.
Program cont v jednom běhu zpracovává vždy jeden zdrojový .cc
soubor, včetně všech do něj vkládaných hlavičkových souborů. Po celou dobu běhu si v paměti udržuje informace o všech definovaných a vytvořených datových typech, které používá za účelem generování dalších datových typů prostřednictvím šablon.
Sledované datové typy jsou popsány jejich jménem, skutečným jménem, množinou zkratek, a jejich vlastnostmi.
Jméno datového typu
Základní jméno datového typu, které je použito jako jméno struktury reprezentující vygenerovaný datový typ. Jméno datového typu může být popsáno formátem splňujícím vlastnosti standardního identifikátoru v jazyce C/C++.
Skutečné jméno
Skutečné jméno datového typu slouží k jednoznačné identifikaci typu za účelem hledání duplicitních datových typů co se obsahu týká. Skutečné jméno datového typu je generováno automaticky na základě typu šablony a datovém typu pro který se tato šablona generuje. Skutečná jména některých datových typů mohou vypadat následovně:
bi_a
- pole celých čísel.bi_a_q
- řada polí celých čísel.bd_l
- seznam (list) 64 bitových reálných čísel.Množina zkratek
Množina zkratek přiřazená k datovému typu obsahuje jména, která se používají pro identifikaci datového typu v rámci zdrojových souborů. První zkratka je nastavena podle jména datového typu. Zbytek zkratek je definován prostřednictvím klíčového slova typedef
.
Vlastnosti datového typu
Datový typ vždy patří do jedné z následujících základních kategorií:
basic
- základní datový typ. Do této kategorie patří například datové typy: char
, int
a double
.static
- datový typ popsaný statickou strukturou, která nepoužívá dynamicky alokovanou paměť.dynamic
- datový typ popsaný dynamickou strukturou, která používá dynamicky alokovanou paměť.Z příslušnosti k jedné z výše uvedených kategorií vyplývají základní vlastnosti datového typu, definující množinu operací, které je možné nad daným datovým typem používat. Tyto informace jsou zohledňovány při generování kontejnerů operujících nad konkrétním datovým typem.
Například pří kopírování pole prostřednictvím metody operator=
je možné pro datové typy z kategorií basic
a static
použít funkci memcpy
, zatímco datové typy dynamic
je nutné kopírovat prostřednictvím jejich operátoru operator=
.
V rámci popisu datového typu může být nastaven příznak flushable
, který indikuje, že je možné zavolat metodu flush
tohoto objektu, za účelem uvolnění přebytečně alokované dynamické paměti.
Datové typy, které jsou určeny pro zpracování jako objekty z kategorií static
a dynamic
musí implementovat následující rozhraní:
init
- Inicializace objektu. Po zavolání této metody se objekt nachází v definovaném stavu a neodkazuje se na žádnou dynamicky přidělenou paměť. Tato metoda se volá nad objekty, které se nachází v nedefinovaném stavu.clear
- Uvolní dynamicky alokovanou paměť používanou objektem a uvede objekt do definovaného stavu. Výsledný stav objektu je stejný jako stav ve kterém se objekt nachází po zavolání metody init
.flush_all
- Omezí velikost dynamicky alokované paměti používané objektem na velikost nezbytně nutnou pro uložení aktuálního obsahu.swap
- Prohodí data přiřazená objektu s daty objektu předaného parametrem metody.operator=
- Zkopíruje do objektu data objektu předaného parametrem operátoru. Původní data objektu jsou uvolněna.operator==
- Porovná objekt s objektem předaným parametrem operátoru a vrátí true
pokud je obsah objektů shodný.Datové typy, které jsou generovány šablonami, implementují výše uvedené rozhraní tak, aby bylo možné tyto datové typy použít pro další generování prostřednictvím šablon.
Původní implementace programu cont byla napsána v jazyce perl, a z množiny vstupních zdrojových souborů generovala jeden výstupní soubor, obsahující veškerý kód překládaného programu. Kvůli rozšiřování funkčnosti programu cont, změně způsobu práce se vstupními soubory a tomu, že nejsem žádný perl hacker byl program cont přepsán do jazyka C/C++. Aktuální syntaxe popisu značek se vyvinula z původní perlem zpracovávané syntaxe, a je možné, že to na ní zanechalo nějaké stopy.
Značky generátoru
Značky generátoru jsou ve zdrojovém souboru uzavřeny mezi klíčovými slovy @begin
a @end
.
@begin
<operation>
<operation>
...
@end
Mezi těmito klíčovými slovy mohou být zapsány značky, provádějící jednu z následujících operaci:
Soubor popisující rozklad výše uvedeného zápisu je k nahlédnutí zde.
Program cont pracuje s hlavičkovými soubory, protože musí mít přehled o datových typech, které byly v těchto souborech definovány nebo vygenerovány. Hlavičkové soubory jsou zpracovávány rekurzivně, což znamená, že soubor vygenerovaný programem cont obsahuje všechny informace, které vstupují do překladu. To neplatí pro standardní direktivy #include
, které se pouze zkopírují do generovaného výstupu, a tyto zpracuje preprocesor jazyka C/C++.
@begin
include "basic.h"
@end
Značka registruje existující datový typ pro použití v rámci generátoru kontejnerů. Tato funkce slouží k propagaci informace o existenci daného datového typu a jeho základních vlastnostech do runtime programu cont.
define <type-id> <modifier> <modifier> ...
Modifikátory ve výše uvedeném řetězci mohou nabývat následujících hodnot: basic
, static
, dynamic
a flushable
.
typedef void * pointer;
@begin
define pointer basic
@end
Tato operace generuje nový datový typ na základě šablony popsané v rámci implementace programu cont. Kód generující požadovaný datový typ se ve zdrojových souborech programu zapisuje na třech místech v následujících třech krocích:
Vygenerování nového datového typu
Značka pro generování nového datového typu obsahuje identifikaci typu kontejneru, identifikaci datového typu (případně několika datových typů) nad kterým bude kontejner vygenerován a jméno nového datového typu. Jméno datového typu nad kterým bude kontejner vygenerován musí existovat a jeho vlastnosti musí být programu cont známy. Níže uvedený formát značky pro vytvoření nového datového typu reprezentuje jen základní možností, rozšířený popis bude uveden níže.
@begin
<cont-id><<type-id>> <new-type-id>;
@end
Ve výše uvedeném zápisu <cont-id>
identifikuje typ kontejneru, <type-id>
identifikuje datový typ, nad kterým bude kontejner vygenerován, a <new-type-id>
identifikuje jméno nově vytvořeného datového typu. Ve zdrojových souborech, kde se nachází tato značka, bude vygenerována struktura popisující nový datový typ reprezentující požadovaný kontejner. Od tohoto bodu dále je možné používat jméno nového datového typu při generování dalších kontejnerů, nebo jako datový typ C/C++ reprezentovaný strukturou.
// -- ui_array_s --
@begin
array<unsigned> ui_array_s;
@end
Vygenerování inline metod datového typu
Ve zdrojových souborech, kde se nachází níže uvedená značka, budou vygenerovány inline metody zvoleného datového typu.
@begin
inlines <type-id>
@end
Ve výše uvedeném zápisu <type-id>
identifikuje vygenerovaný datový typ. Tuto značku je možné použít kdekoli ve zdrojových souborech, ale ve většině případů se používá ve stejném hlavičkovém souboru, ve kterém byl daný datový typ vygenerován. To proto, aby překladač C/C++ měl přístup k implementaci inline metod při kompilaci všech .o
objektů ve kterých je datový typ nadefinován.
// -- ui_array_s --
@begin
inlines ui_array_s
@end
Vygenerování metod datového typu
Ve zdrojových souborech, kde se nachází níže uvedená značka, budou vygenerovány metody kontejneru.
@begin
methods <type-id>
@end
Ve výše uvedeném zápisu <type-id>
identifikuje vygenerovaný datový typ. Tato značka se použije ve zdrojovém .cc
souboru, který bude obsahovat implementaci funkce generovaného kontejneru.
// -- ui_array_s --
@begin
methods ui_array_s
@end
Značka určená pro popis datového typu generovaného na základě šablony může mít komplikovanější formát, než ten který byl uveden v předcházejícím textu. Tato značka musí umožňovat:
@begin
<cont-id>
<
<type-id>:<var-name>
...
>
not_generate: <method-id> ...
options: <option> ...
additions
{
<addition-code>
...
}
<new-type-id>
...
;
@end
V uvedeném zápisu mají jednotlivé zástupné hodnoty následující význam:
<cont-id>
- Identifikuje typ generovaného kontejneru.<type-id>
- Datový typ nad kterým bude kontejner generován.<var-name>
- Zastupuje jméno členské proměnné, přiřazené k datovému typu.<method-id>
- Identifikace metody, která bude vynechána při generování obsahu struktury. Tato identifikace může nabývat hodnot: init
, clear
, swap
, operator=
.<option>
- Rozšiřující volba, která může nabývat hodnoty strict_dynamic
.<addition-code>
- Rozšiřující kód, který umožňuje přidat členské proměnné a metody do deklarace generované struktury. Kód uzavřený ve složených závorkách je zkopírován do generovaného C/C++ souboru beze změny.<new-type-id>
- Jméno identifikující nově generovaný datový typ. První jméno je použito jako jméno generované struktury. Zbytek jmen je nadefinován pomocí klíčového slova typedef
.V této části textu uvedu stručný popis jednotlivých typů šablon, na základě kterých je možné generovat nové datové typy.
Šablona struct - struktura shlukující několik prvků
Tato šablona slouží za účelem kombinování jednodušších datových typů do složitějšího celků. Její význam je stejný jako význam struktury (struct
) v jazyce C. Příklad použití šablony generující strukturu je uveden zde.
// -- record_s --
@begin
struct
<
unsigned:index
unsigned:value
>
record_s;
Šablona array - dynamické pole prvků
Tato šablona generuje abstraktní datový typ reprezentující dynamické pole s možností vkládat nové prvky na jeho konec. Dynamické pole je vhodné pro implementování abstraktního datového typu zásobník (LIFO). Příklad použití šablony generující dynamické pole je uveden zde.
// -- rec_array_s --
@begin
array<record_s> rec_array_s;
@end
Šablona queue - dynamická řada prvků
Tato šablona generuje abstraktní datový typ reprezentující jedno-směrnou řadu. To znamená, že prvky jsou vkládány na konec řady a je možné je vyzvedávat ze začátku řady (FIFO). Příklad použití šablony generující dynamickou řadu prvků je uveden zde.
// -- rec_queue_s --
@begin
queue<record_s> rec_queue_s;
@end
Šablona list - obousměrný seznam prvků
Tato šablona generuje abstraktní datový typ reprezentující obousměrný seznam. Jednotlivé prvky je možné do tohoto seznamu vkládat na libovolnou pozici, a z libovolné pozice je odstraňovat. Prvky jsou v obousměrném seznamu identifikovány celým bez-znaménkovým číslem. Příklad použití šablony generující obousměrný seznam prvků je uveden zde.
// -- rec_list_s --
@begin
list<record_s> rec_list_s;
@end
Šablona rb_tree - Automaticky vyvažovaný binární strom
Tato šablona generuje abstraktní datový typ reprezentující automaticky vyvažovaný binární strom, jehož nejdelší větev je maximálně dvakrát tak dlouhá jako jeho nejkratší větev. Prvky jsou do stromu vkládány s logaritmickou složitostí, a se stejnou složitostí jsou v tomto stromě vyhledávány. Prvky jsou ve stromě identifikovány celým bez-znaménkovým číslem. Příklad použití šablony generující automaticky vyvažovaný binární strom je uveden zde.
Metoda get_idxs
objektů generovaných touto šablonou používá datový typ ui_array_s
popisující dynamické pole celých bez-znaménkových čísel. Proto je nutné tento datový typ vygenerovat před generováním ze šablony rb_tree
.
V rámci objektu generovaných že šablony rb_tree
je nutné implementovat jejich metodu __compare_value
(příklad zde), která je používána pro porovnání dvou prvků tohoto kontejneru.
// -- rec_rb_tree_s --
@begin
rb_tree<record_s> rec_rb_tree_s;
@end
Pro potřeby následujícího popisu vlastností generovaných kontejnerů předpokládejme, že existuje datový typ string_s
, který má dvě členské proměnné length
(celé číslo) a data
(ukazatel na znaky). Dále předpokládejme, že na základě tohoto typu byly vygenerované datové typy string_array_s
a string_list_s
.
Umístění objektů v jednom bloku paměti
Statická data struktur datových typů obsažených v kontejneru jsou umístěna v jednom bloku paměti, který je možné při dynamické změně velikosti zkopírovat funkcí memcpy
. V našem případě v rámci implementace datového typu string_array_s
vznikne následující struktura:
struct string_array_s
{
unsigned size;
unsigned used;
string_s *data;
}
V objektu typu string_array_s
je alokován blok paměti obsahující data struktury string_s
. V případě realokace pole je alokován větší blok paměti, na jehož začátek je zkopírován obsah starého bloku, a starý blok je následně uvolněn. S dynamickými daty objektů typu string_s
se při realokaci manipulovat nemusí, protože ukazatele na ně se zkopírují do nového aktivního bloku. Jednotlivé řetězce je možné indexovat celým číslem identifikujícím jejich pozici v bloku paměti.
Výše uvedené je více méně samozřejmostí pro datový typ reprezentující dynamické pole, podstatné je, že tyto vlastnosti jsou vlastní všem datovým typům generovaným šablonami programu cont, včetně obousměrného seznamu a red-black stromu.
Demonstraci použitého principu předvedu na objektu generovaného na základě šablony list
. V rámci implementace datového typu string_list_s
vzniknou následující struktury:
struct string_list_s_element
{
string_s object;
unsigned next_idx;
unsigned prev_idx;
};
struct string_list_s
{
unsigned size;
unsigned used;
string_list_s_element *data;
unsigned free_idx;
unsigned first_idx;
unsigned last_idx;
}
Výše uvedená struktura string_list_s_element
je použita jako základní prvek bloku paměti přiřazeného kontejneru string_list_s
. Díky tomu je možné obdobně jako u pole identifikovat prvek vložený do seznamu pomocí celého čísla, udávajícího offset od začátku bloku paměti. Tuto vlastnost využívají indexy výše uvedených struktur, identifikující jeden konkrétní prvek seznamu.
Prvky odstraněné ze seznamu se recyklují při vkládání nového prvku, a v případě, že není žádný volný prvek k dispozici, realokuje se nosný blok paměti stejným způsobem jaký byl popsán u objektu typu string_array_s
.
Indexace kontejnerů pomocí celého čísla
Z výše uvedeného způsobu implementace kontejnerů vyplývá, že celočíselný index přiřazený prvku vloženému do kontejneru je neměnný po celou dobu jeho života v tomto kontejneru. Jinými slovy: celočíselný index pozbývá platnosti pouze odstraněním tohoto prvku z daného kontejneru.
Tato vlastnost usnadňuje vytváření pohledů, funkcí a různých mapování mezi kontejnery. Kvůli této vlastnosti byly kontejnery a jejich generátor navržen a implementován, a tato byla využita při implementaci algoritmů pro vyhledávání množiny isomorfních grafů v ohodnoceném hostitelském grafu.
Safe varianty šablon list a rb_tree
Šablony safe_list
a safe_rb_tree
generují "bezpečné" varianty odpovídajících datových typů. Tyto navíc (oproti standardním implementacím) udržují počítadlo aktuálního počtu prvků v kontejneru, a u každého prvku udržují příznak indikující, zda je tento aktivním prvkem kontejneru. Tato vlastnost je užitečná v případě, že celočíselné indexy identifikující prvek pochází z vnějšího zdroje, a je potřeba otestovat, zda takový index odkazuje na validní prvek kontejneru.
Program cont generuje svůj vlastní zdrojový kód. Generátor je implementován s využitím značek, k jejichž generování je určen. V repositáři obsahujícím zdrojový kód programu cont jsou uloženy i vygenerované soubory určené k jeho první kompilaci.
Tiskni
Sdílej:
Dobrá tedy, tak na té nesrozumitelnosti asi něco bude.
Co to dělá: Zdrojové soubory kompilovaného projektu obsahují značky, které popisují datové typy, které se mají generovat na základě podporované množiny šablon.
Program o kterém píši, prochází zdrojové soubory kompilovaného projektu, hledá v něm tyto značky, a generuje kód implementující datové typy popsané těmito značkami. Vygenerovaný výsledný soubor je určen ke kompilaci kompilátorem C/C++.
Pokud znáte STL a kontejnery (vector, list, atd.), tak to v podstatě dělá to samé, jen jsou tyto značky zpracované externím preprocesorem (programem cont).
Ano je to víceméně tak jak píšeš. Jen mapy nejsou implementovaný jako samostatný typ kontejneru, a je potřeba tyto vytvořit jako kombinaci struktury obsahující integer index
a string value
, nad kterou se vygeneruje rb_tree
.
Příklad generování mapy int na string výše uvedeným způsobem je uveden zde.
Struktura int_string_s
je generována nad nějakým mým obskurním řetězcem, protože struktury použité v kontejnerech musí implementovat rozhraní, které jsem zmiňoval v zápisku.
Značky generující kontejnery jsou ve zdrojových souborech umístěny zde.
Nesnažím se tvrdit, že je to lepší než STL šablonové kontejnery, případně jiná implementace kontejnerů, to by jsem si ani tvrdit netroufal.
Typy kontejnerů, které to je schopné generovat jsem se snažil popsat v zápisku. Výhody oproti STL jsou pro mě následující:
Hlavním důvodem proč jsem jsem se tu o tom upsal bylo, že to používám ve větší věci, kterou tu chci zmínit, a byl by jsem rád, kdyby někdo kdo se případně podívá na zdrojové kódy a viděl tam tyto značky, tak aby tušil která bije.
Když jsem implementoval grafové gramatiky reprezentoval jsem množiny vrcholů a hran grafu rb-stromy, kde:
Tyto "odkazy" na hrany a uzly byly realizované pomocí celých čísel (unsigned
), tak jak o nich píši v zápisku (viz "Umístění objektů v jednom bloku paměti"). Takto popsaný graf bylo snadné exportovat do binárního souboru, a z tohoto jej importovat, jednoduchým zkopírováním bloků paměti generovaných kontejnerů (offset zůstal zachován).
Některé z důvodů proč jsem v té době nepoužil STL:
Před tím, než jsem vytvořil tento preprocesor, jsem zkoušel za účelem generování kódu používat makra preprocesoru, a později i C++ šablony. Ale vždy jsem narazil na nějaké omezení, které se mi nelíbilo.
Já jsem takový úchyl, kterému by se líbilo, kdyby jazyk C preprocesoru byl úplný programovací jazyk, který by generoval zdrojový soubor pro překladač.
Šablony jsou určitě nástroj, který by člověk myslící to s C++ vážně neměl ignorovat. Před 6 lety, kdy jsem vytvářel preprocesor, se mi šablonování zdálo docela divoké, ale v poslední době, když se setkám s novými věcmi z C++11, tak bývám často překvapen, v dobrém slova smyslu.
Problémy (které si myslím že mám) s C++ šablonami:
Já jsem takový úchyl, kterému by se líbilo, kdyby jazyk C preprocesoru byl úplný programovací jazyk, který by generoval zdrojový soubor pro překladač.Taky bych bral nějaký hybrid mezi céčkem a tím, co jsem slyšel o lispu.
Já jsem takový úchyl, kterému by se líbilo, kdyby jazyk C preprocesoru byl úplný programovací jazyk, který by generoval zdrojový soubor pro překladač.Zkus D. Tam přesně takhle fungují template mixiny.
Problém je v tom, že programuji spíše v jazyce C, než v C++. Z C++ si beru jen syntaktický cukr týkající se metod a referencí. Potvrzením tohoto budiž fakt, že bylo poměrně snadné upravit generátor kódu tak, aby jeho výstup bylo možné zkompilovat kompilátorem jazyka C (branch cont_c).
Na šablony, jsem zanevřel před šesti lety, předtím, než jsem generátor začal používat. V okamžiku, kdy použiji šablony jsem odsouzen programovat v C++ naplno (konstruktory/destruktory, new/delete, instanciace šablonových funkcí, ...), ale to já nepotřebuji, proč by jsem musel? Namísto zjednodušení mi výše uvedené do problémů zanáší další úroveň složitosti.
S příchodem C++11 (nebo spíše s přibývající podporou v kompilátorech) to začíná být znovu zajímavé. Vypadá to, že už se upustilo od čisté teorie a někdo se to (šablony) pokusil použít v praxi a získanou zkušenosti promítl do C++11. To nic nemění na tom, že například Texas Instruments nepodporují v některých svých kompilátorech tyto "kouzla" (C++11 traits), na rozdíl od C++ jak jej používám já, a které bude vždy a všude přístupné. Ale i v budoucnu, kdy bude podpora "kouzel" už dostatečná by jsem musel odmítnout názor tvrdící, že když jazyk podporuje generické programování, tak dělat to jiným způsobem je rouhání (neříkám, že to tvrdíte).
Na C a C++ s objekty mi vyhovuje minimální množství axiomů, které programátor musí znát, aby mohl naprogramovat cokoli. Pokud má někdo problém s dynamickou pamětí a inicializací proměnných (konstruktory, destruktory), ukazateli (iterátory, smart ukazatele), vstupem/výstupem (streamy), dobrá ať si to zjednoduší, za cenu toho, že se připraví o určitou svobodu, ale nemusí takový přístup vyžadovat i od ostatních (pokud ovšem není projektový manager, rozhodující o používaných nástrojích).
Je to tak jak říkáš. Proto pořád píši C/C++ namísto C++, čímž mám na mysli C rozšířené o metody ve strukturách, reference, datový typ bool, výčtový typ, a možná některé další funkce.
Původně to (v experimentální fázi) generovalo C kód, a generované funkce vypadaly tak jak je vidět v některých C knihovnách: rb_tree_init, rb_tree_push, apod. Od toho jsem ale upustil, protože pohodlnost použití vygenerovaných "objektů" byla ještě horší.
Aktuálně generovaný kód překladačem C přeložit nejde, ale je jednoduché to upravit tak, aby takový kód byl generován.
Problém je jen v tom, že C nezná metody ve strukturách, reference a typ bool
. Kód generátoru je možné upravit tak, aby místo metod generoval funkce s prefixovou notací (<class>_<method>
), a reference nahradil ukazateli. Algoritmy zůstávají stejné.
Včera jsem vykoušel jeden generátor takto upravit, a funguje to.
Včera jsem vykoušel jeden generátor takto upravit, a funguje to.Však keby si do blogov napísal konkrétne prípady použia, tak by to viac povedalo ako stovky riadkov teórie
Inu chtěl jsem aby to bylo kompletně popsané :). Jinak jsem tam uvedl nějaké odkazy na příklady pro každý popsaný kontejner. Nebo případem použití máš na mysli nějaký konkrétní program, ve kterém jsem to použil? Třeba parser generátor yapgen je na tom kompletně založený.
Transformace do C výstupu už je v pokročilé fázi, jsem zvědavý na porovnání výsledku překladu C vs C++ co se rychlostí výsledného kódu týká (i když tuším, že se to nijak lišit nebude).
Jinak ty generované kontejnery v C/C++ používám docela často ve věcech na kterých dělám, a dost jsem si na to zvykl. Šablony v C++ mě zatím nějak míjí.
IMHO by se dala udelat implementace v cistem C++, ktera by se chovala naprosto stejne jako C++ vystup z cont. Sablony nejsou zas takova veda, pokud jde o containery. Urcite by i slo vyuzit ty algoritmy.