Portál AbcLinuxu, 30. dubna 2025 10:15
Tak nějak jsem byl nespokojen s textovým editorem, co jsem používal na Linuxu (Geany), nelíbil se mi třeba způsob definice externích příkazů a pár dalších bugů (hlavně ve vykreslování Scintilly). Tak si píšu svůj textový editor.
Repo najdete tady. Na wiki mám i takový jednoduchý přehled některých funkcí.
O tohle mi šlo hlavně, chtěl jsem, abych si mohl přehledně definovat jednotlivé externí tooly a zároveń si je dát do kategorií (podmenu).
Další věc je, aby fungovalo sdílení nastavení (třeba přes Dropbox) mezi různými platformami. U ostatních prohlížečů se mi většinou stávalo, že třeba ty definice externích utilit mi nefungovaly, i když jsem měl daný interpret (bash) dostupný na obou mašinách (windows a linux). Taky se mi stávalo, že některá nastavení se mi prostě při otevření programu na jiném stroji ztratila. Proto jeden z hlavních cílů je, aby uživatelské nastavení bylo plně portabilní, bez výjimek.
Tiskni
Sdílej:
Kde se tyhle věci učíš? Nějaké weby, knížky…? Já mám Mistrovství v C++, ale to je deset let stará kniha, a pak různé náhodné zdroje, co najdu na internetu, když řeším něco konkrétního. Ale hodil by se mi nějaký ucelený výklad moderního C++.
std::move
, etc). Navíc už tak vysoká komplexita jazyka tím ještě roste... Třeba value categories už mi přijdou dost šílený.
Ale jsem rád, že to v tom jazyce je, protože to je fakt hodně užitečný.S tim naprosto souhlasim, jen úplně nejsem nadšnej z toho, jakým způsobem se to do toho jazyka integruje. Ty složitosti ohledně rvalue referencí jsou v zásadě skoro celé způsobené zpětnou kompatibilitou. K move semantics v C++ jsem přišel až po zkušenosti z Rustu (který byl tehdy sice v plenkách, ale zrovna tohle se od té doby jen málo změnilo) a oproti tomu je to v C++ hrozně nepohodlné, navíc C++ v podstatě jako takové ani move semantics nepodporuje, pouze máš k dispozici to primitivum rvalue references, nad kterým to můžeš naimplementovat, pokud to uděláš spránvě a nenaběhneš si přitom na nějaký hrábě, kterých C++ má dost. Je sice hezký, že přidávají užitečný featury - třeba koncepty se mi samy o sobě taky líbí - ale s dřívějšími, dnes už spíše historickými vlastnostmi jazyka to moc nejde dokupy a má to tendenci vytvářet šílenou komplexitu a přidávat další ležící hrábě. Pokud by se měly přidat koncepty, moduly a další "velký" fíčury, už by to IMHO bylo na zvážení, jestli neporušit zpětnou kompatibilitu, alespoň třeba v nějakým omezeným režimu (třeba na úrovni souborů nebo nějakých bloků nebo tak něco), jinak z toho bude naprosto šílenej guláš.
Opravdu jsou tyhle kosmetický záležitosti natolik cool, že se kvůli nim vyplatí obětovat kompatabilitu s mnoha současnými systémy/distribucemi?!
new
a delete
. Oproti tomu jsou ty ostatní věci opravdu spíš kosmetika.
Jinak zajímalo by mě, které systémy/distribuce má kolega na mysli. Nejsem si 100% jistej, ale AFAIK třeba gcc na Debianu Wheezy ty výše zmíněný fíčury podporuje. Je ještě nějaké konzervativnější distro? Zrovna ty zmiňovaný fíčury jsou IMHO všechny c++11, takže tam už to dneska (kromě RHEL6) prakticky není problém, nicméně v původním příspěvku se hovořilo o c++14 a to už nepřeložíte ve spoustě distribucí, např. v aktuálním RHEL7.
shared_ptr
, když chci, aby se to pak „samo uklidilo“, nebo to jde nějak elegantněji?
shared_ptr
pokud možno vyhnout, protože sdílená zodpovědnost za dealokaci zdroje většinou vnáší zmatek. Je opravdu jen málo případů, kdy je shared_ptr
dobrý nápad. V jiných případech je lepší najít si konkrétní část programu, která má nést za daný zdroj zodpovědnost.
Dobře. A dá se to tedy v C++ nějak udělat, aby s tím šlo pracovat aspoň tak dobře jako v Javě? Tzn. do mapy nastrkám objekty k nějakým klíčům a když pro daný klíč přepíšu hodnotu nebo záznam odstraním, tak se uklidí i ten objekt (pokud ho nikdo další nepoužívá). Totéž v případě, že už nikdo nepoužívá tu mapu – pak by měla zmizet celá včetně klíčů a hodnot.
std::
, je zodpovědná za dealokaci objektů, které vlastní. Ať už je to int
, std::string
, nebo třeba std::shared_ptr
.
A když tu hodnotu z mapy vytáhnu a budu zároveň používat i někde jinde, jak se pozná, kdy je možné ji uvolnit?
Proč bych dělal kopii, když chci tu samou instanci?
==
.
Kopie ukazatele ať se klidně udělá, to je mi jedno. Ale jde mi o to, že mám instanci nějaké třídy. Tuto instanci může být nákladné vytvořit (načte se konfigurace, něco se vypočítá atd.) nebo má držet nějaký společný stav → takže chci mít jen jednu instanci a nechci ji kopírovat. Tuhle instanci chci dát do mapy, abych ji mohl vyhledávat podle nějakého klíče. A když už tu instanci nikdo nepotřebuje (v mapě jsem danému klíči přiřadil jinou instanci a ani jinde tuhle instanci nikdo nepoužívá), tak by se měla „sama uklidit“ (resp. někdo ji uklidí, ale nechci to hlídat ručně). Tohle se tedy dělá tak, že dám ty shared_ptr
do mapy nebo to jde nějak elegantněji?
Tohle se tedy dělá tak, že dám ty shared_ptr
do mapy nebo to jde nějak elegantněji?
Sorry, ale na to se IMHO nedá rozumně odpovědět. Možná ne, možná jo, podle toho, co to je za objekt a jakým způsobem ho chceš používat. Přijde mi, že popisuješ jakoby javovský návrh, který se snažíš namapovat na konstrukty v C++, ale to prostě nejde, protože ty jazyky nemapují 1:1.
Velký rozdíl je např. v tom, že v Javě do kontejnerů dáváš objekty (resp. reference na objekty), kdežto v C++ obecně jakýkoli hodnoty a "objekty" jsou toho jen specielní případ, navíc různě stejný nebo jiný podle toho, jakým způsobem. Atd. Opravdu se na tyhle dotazy těžko odpovídá. Přijde mi, že by bylo mnohem snažší začít s C++ víc na zelené louce a nesnažit se na něj namapovat Javu.
ale stačí se podívat na režimy předávání argumentů (value, reference, pointer) a člověk vidí, že je něco trochu špatněAž do téhle věty jsem souhlasil, tohle ale moc nechápu. Předání hodnotou vs pointerem máš v C úplně stejně. Navíc je v C++ oproti C jen ta reference, která IMHO v C++ celkem dává smysl, jako takový "bezpečnější" (a optimalizovatelnější) pointer (ona ta reference nejde tak daleko jako třeba v Rustu, kde je skutečně bezpečná, no nicméně to není zaměření C++). Koneckonců, ono i v tom C je vidět potřeba pro něco takového - viz přidání
restrict
.
V C++ se dá udělat to samé jako v javě tak, že všude použiješ shared pointery.Tady nemůžu tak úplně souhlasit, protože GC v Javě řeší cykly, zatímco shared pointery ti klidně leaknou cyklus, což může způsobit nejen memory leaky, ale v horším případě třeba neuzavření dalších zdrojů, transakcé a kýho čerta... To je mj. další důvod, proč není dobrý nápad je používat víc, než je nutné.
Teda většinou, narazit na to můžeš např. ve chvíli, kdy se pokusíš porovnávat instance pomocí operátoru ==.
V Javě? Můžeš uvést příklad? Když dám do mapy nějaký objekt a pak si ho pod daným klíčem vyzvednu, tak se budou rovnat, bude to ta samá instance, ne kopie. Nebo myslíš něco jiného?
Proč bych dělal kopii, když chci tu samou instanci?Protože nemáš navýběr. Bavíme se o kontextu, kdy máš fyzicky v paměti pole objektů. Nemůžeš si jen tak vzít ten kus paměti, když je součástí toho pole.
BTW: jak je to s mapami a chytrými ukazateli? Je potřeba mít v mapě jako typ hodnoty shared_ptr
, když chci, aby se to pak „samo uklidilo“, nebo to jde nějak elegantněji?
To záleží, co myslíš tím "samo uklidilo". Hashmapy stejně jako další kolekce ze standardní knihovny samozřejmě "uklízejí" po sobě v tom smyslu, že při smazání prvku z kolekce volají destruktor toho prvku. Jestliže ti to stačí, pak smart pointer nepotřebuješ, stejně jako nepotřebuješ smart pointer, pokud do té mapy dáváš POD typy.
Pokud bys chtěl do mapy uložit pointer na objekt a zároveň k němu přistupovat nezávisle ještě někde jinde (tj. sdílené vlastnictví), budeš nejspíše potřebovat shared_ptr
nebo něco podobného, ale doporučoval bych spíš se zamyslet nad návrhem a zkusit to třeba udělat jinak. Vzhledem k tomu, že v C++ musíš řešit vlastnictví a druh přístupu, Javovský návrh ti moc nepomůže, spíše naopak.
Dejme tomu, že v té mapě chci držet nějaké moduly nebo procesory jako hodnoty a klíčem bude kód příkazu/operace nebo nějaký typ úlohy. Pak mám někde frontu přicházejících požadavků, vždycky se podívám na jeho typ a podle něj to pošlu do správného procesoru z mapy (celé to bude schované v nějaké metodě). To se může dít i ve víc vláknech… Konfigurace procesorů se může v čase měnit a ty staré již nepotřebné by se měly uklidit. Ale pokud procesor ještě pracuje, musí doběhnout, nikdo by ho neměl smazat. Těmi vlákny se to ještě komplikuje o synchronizaci, ale i bez těch vláken je snad jasné, co mám na mysli. Je mi jasné, že to nikdy nebude jako GC, ale chtěl bych něco, co se tomu komfortem a bezpečností alespoň blíží případně poradit nějaký jiný návrh, který bude lepší. Dávat shared_ptr
do mapy jsem zkoušel, ale vypadalo to fakt hnusně – snad existuje nějaká lepší cesta, jak s tím pracovat.
shared_ptr
, nemusel bys tu mapu zamykat, ... Tyhle otázky, jako co kdo vlastní a jaký má kdo kam přístup, se v Javě řeší až ex post nebo vůbec. Tady to ale musíš řešit dopředu nebo nejpozději během tvorby programu.
Pravidla palce: Používej primárně const
přístup a mutabilní přístup až když si jsi jistý, že to je správně. Tj. proměnné jsou const by default, ditto member funkce (const
na konci deklarace). Věci do funkcí předávej primárně const referencí nebo movem, u menších POD/POD-like typů hodnotou. Jinými až způsoby, hlavně mutabilní referncí, opět jen až když víš jistě, že to je správně a nejde to jinak. Používej primárně přímé vlastnistcí bez heap alokace, pak unique_ptr
, pak teprve až něco dalšího (třeba shared_ptr
).
Sdílené vlastnictví a sdílený mutabilní přístup by měly být až poslední instance, kór když je to ještě navíc mezi vlákny.
Teď zrovna řeším něco hodně primitivního*, kde ani vlákna nejsou, ale snažil jsem se nad tím přemýšlet, jak by to vypadalo v o trošku složitější aplikaci. Máme nějaký vstup, proud zpráv potažmo volání metod. Ty zprávy můžou přicházet i z víc vláken. Zprávy je potřeba nějak roztřídit a poslat „procesorům“ Procesor se zprávou něco provede, někam odešle výsledek… To směrování zpráv může být mnohem složitější, ale prozatím uvažujme, že se budou třídit jen podle typu – textového klíče. Tudíž mi přišlo celkem přirozené použít mapu. Těch procesorů by mohlo být od každého typu víc a mohli bychom balancovat s tím, že vytvoření procesoru na jedné straně spotřebovává nějaký výpočetní výkon a procesor následně zabírá víc paměti a na druhé straně víc procesorů může lépe pracovat paralelně… tohle by se dalo nějak dynamicky konfigurovat a měnit za chodu – ale opět to nechci zesložiťovat, takže pro jednoduchost jsem chtěl zatím jen jeden procesor od každého typu.
*) Má to být interpret příkazů, které budou řídit RGB LED diody. Nakonec to poběží na nějakém jednočipu, ale nejdřív jsem si to chtěl vyzkoušet na „stolním“ C/C++ a udělat si tam prototyp, kde si ujasním formát, příkazy atd. Na vstupu bude posloupnost bajtů a výstupem je, že to různě rozsvěcí RGB LEDky. V podstatě takový jednoúčelový assembler. Je to taková blbost, ale říkal jsem si, že se na tom něco naučím. Má to fungovat tak, že tomu pošleš tu posloupnost bajtů a pak to pojede samo – tzn. v jednom programu si připravíš tu posloupnost (zatím to budu psát ručně), pošleš ji jednorázově jinému programu, ukončíš s ním „spojení“ a v tom druhém programu to pojede. Tzn. nemusíš pokaždé přeflashovat jednočip, aby jinak blikal, jen mu pošleš ty bajty, on si je uloží do RAM a bude je interpretovat. Příkazy můžou být typu: čekej X ms (jeden bajt je ID příkazu, pak jsou volitelně parametry, které můžou být různě dlouhé podle příkazu), nastav intenzitu určité barvy (parametr) na určité diodě (parametr) na hodnotu, kterou najdeš na Xté (parametr) pozici v té posloupnosti bajtů, inkrementuj/dekrementuj hodnotu na Xté pozici, nastav barvu na pevně danou hodnotu (parametrem příkazu je přímo ta hodnota, ne odkaz na její pozici), GOTO na určitou pozici, podmíněné GOTO, které porovná hodnoty na dvou pozicích nebo hodnotu proti konstantě atd. V té posloupnosti tedy nebudou jen data, ale může tam být i nějaká logika, v podstatě program.
Např. při bootu počítače to to tam pošle jednu sekvenci bajtů a od té doby to bude nějak blikat/svítit, dokud se tam nepošle jiná sekvence – bude se interpretovat pořád dokola (když na konci bude GOTO 0); když nastartuje KDE, tak se tam pošle něco jiného a bude to svítit jinak, když přijde e-mail, tak to třeba začne zuřivě blikat, když pustím videopřehrávač, tak se to ztlumí atd.
Na tom jednočipu to bude muset být zjednodušené, ale zatím si s tím hraji na počítači, kde můžu používat i věci z C++17. Původně jsem to chtěl udělat tak, že co příkaz, to položka v mapě a ukazovalo by to buď na nějakou instanci nebo na funkci. Tady by to bylo asi jedno, protože program se jednou nakonfiguruje a pak už se to nemění, ale schválně jsem si říkal, jak by to bylo u programu, který běží dlouhodobě a během svého života se mnohokrát překonfiguruje, změní se hodnoty v mapě atd. – kdo tam bude uklízet ty staré hodnoty, jak poznat, že už ty instance nejsou potřeba… Pak je taky potřeba si mezi tím nějak předávat odkaz na tu paměť, ze které se čte a případně se do ní i zapisuje.
V té paměti se mimochodem nerozlišuje mezi příkazy a daty, takže by tam šlo dělat různá kouzla/prasárny :-). Kdyby se narazilo na neexistující příkaz nebo došla data, tak by to skočilo na nějakou domluvenou pozici (obdoba odchycení výjimky), kde by se pokračovalo dál. Mohla by se třeba dělat soutěž, kdo v tom napíše nejzajímavější blikání – něco jako se kdysi dělala dema. Paměť by byla omezená hardwarem, takže třeba jen 1024 bajtů.
Na tom jednočipu to bude asi ten switch
(pole by zbytečně zabíralo další RAM), rozhodně to nebude ten samý kód jako u prototypu. Ale na tom desktopu se nad tím snažím přemýšlet, jak by to vypadalo ve větší aplikaci, která běží delší dobu, rekonfiguruje se za chodu, nemá globální kontext (může tam být např. více e-mailových účtů a každý bude mít jiné filtry)… nicméně nemusí to být nutně objektový návrh.
Na tom jednočipu to bude asi ten switch
(pole by zbytečně zabíralo další RAM)
Ne nutně, to pole může být konstatní, tj. společně s kódem v readonly datech. Mohlo by se i stát, že ten switch
bude ve výsledku větší. Záleží samozřejmě na okolnostech, na paměťové architektuře toho jednočipu, na toolchainu atd.
Například ESP8266 umí vykonávat kód z SPI flashe bez kopie do RAM a IIRC C kód může k readonly datům ve flashi přístupovat přes adresní prostor.
P.S. Zatím to mám jako FOR cyklus a v něm SWICH, ale chtěl bych to strukturovat nějak líp a zároveň to udělat nějak dynamicky – např. kdyby ten program měl GUI, tak by sis mohl zvolit, čím se který příkaz (obecně typ zprávy) bude zpracovávat (předvolená množina procesorů). A tahle konfigurace by se za běhu programu měla někde držet (a tam mě právě napadá ta mapa jako nejjednodušší řešení). Kdyby to byl třeba e-mailový nebo IM klient, tak by to mohly být filtry zpráv – v nejjednodušším případě by šlo filtrovat jen podle odesílatele (klíč mapy?) a ten „procesor“ (hodnota mapy?) by třeba zařídil přehrání zvuku, zobrazení upozornění, přesun zprávy do určité složky, automatickou odpověď atd.
Ano, ale mě by právě zajímalo, jak to v C/C++ implementovat tak, aby to nebylo zadrátované v kódu, nýbrž aby to bylo dynamické a šlo to teoreticky měnit za chodu (např. tím, že uživatel něco nakliká v GUI nebo že se načte nový konfigurační soubor z disku). A vlastně původně jsem řešil ještě mnohem primitivnější problém – jak pohodlně pracovat s mapami (obecně kolekcemi) a mít zabezpečenou správu paměti.
Ano, ale mě by právě zajímalo, jak to v C/C++ implementovat tak, aby to nebylo zadrátované v kódu, nýbrž aby to bylo dynamické a šlo to teoreticky měnit za chodu (např. tím, že uživatel něco nakliká v GUI nebo že se načte nový konfigurační soubor z disku).Pokud to vyloženě nepotřebuješ, tak bych to nedělal. Možná máš pocit, že se tim víc naučíš, ale spíš si myslim, že to je tak, že by ses naučil něco jinýho / jinej aspekt. Začal bych co nejjednodušeji.
A vlastně původně jsem řešil ještě mnohem primitivnější problém – jak pohodlně pracovat s mapami (obecně kolekcemi) a mít zabezpečenou správu paměti.Kolekce nejsou nijak specifický co se správy paměti týče. Kolekce si sama spravuje svou pamět, kterou potřebuje. Co se týče "objektů", které do ní dáš a pak smažeš, tak o ně se postará v tom smyslu, že správně zavolá destruktor, když je odstraňuje. A když se volá dtor té kolekce jako takové, tak se zbaví zbývajících prvků, tj. zavolá jejich dtory a uvolní paměť, kterou zabíraly (ale pozor, pouze ty prvky jako takové - tj. když to bude raw pointer, uvolní se pouze ten raw pointer jako takový, už ale ne to, na co ukazuje). Pravděpodobně máš spíše problém obecně se správou paměti, resp. lifetimes, který se jen projevuje při nějaké práci s kolekcemi. Je důležitý, abys měl na paměti, že narozdíl od Javy, kde se pracuje primárně s objekty, v C++ se pracuje primárně s hodnotami a "objekt" je spíš takové vágní označení, které může mít v různých kotextech různý význam. V C++ je všechno obecná hodnota (nějaký shluk bajtů). Kolekce neobsahuje objekty jako v Javě, ale hodnoty nějakého typu. Pojmem "objekt" nejspíš myslíš nějaký pointer na nějakou heap-alokovanou instanci struktury/třídy (zejména v případě smart pointeru to je asi nejblíže té referenci v Javě). Kolekce ti mileráda pointer uskladní (jako každou jinou hodnotu) a na požádání vydá, ale interpretace toho, co ten pointer je a kdy se třeba nad ním má/nemá zavolat dealokace je na tobě a/nebo na smart pointeru (v případě, že se jedná o smart pointer), ta kolekce se o tohle vůbec nestará. Ta hodnota může reagovat na to, když ta kolekce zavolá třeba některý operátor nebo destruktor, ale to je všechno. Díky tomu můžeš mj. také instance ukládat do mapy napřímo bez pointeru, v takovém případě jsou veškerá data instance obsažena fyzicky přímo v prostoru, který si alokuje ta kolekce (tohle v Javě vůbec nejde). V tom případě pak lifetime té instance je svázán s jejím obsažením v té kolekci, ve chvíli, kdy se z kolekce odstraní, zavolá se její dtor (což ti ale stále nebrání ještě před tím tu instanci někam vykopírovat nebo použít move). Dokonce můžeš v dostatečně novém C++ ty instance takhle přímo konstruovat ("emaplacing"). Jestli dává smysl mít ty instance v kolekci napřímo nebo přes pointer, případně přes jaký druh pointeru, to je něco, co si musíš vymyslet sám tak, aby to co nejlépe sedělo na tvůj usecase (a je pravda, že to asi vyžaduje určitou znalost / zkušenost, kterou někdo, kdo přišel z Javy, asi mít nebude). Možná by sis mohl zkusit naimplementovat svou vlastní verzi smart pointerů jako
unique_ptr
a shared_ptr
, to by mohlo vést k lepšímu porozumění tomu, jak fungují (a že to jsou vlastně jen zase celkem jednoduchý hodnoty). Když člověk neřeší 100% korektnost, atomicitu, atd., tak to je na pár řádků (že to nebude 100% korektní ve všech corner-casech nevadí, jde jen o ten principielní základ). Určitě by nebylo špatné si vytvořit nějakou dummy třídu, která bude třeba vypisovat na výstup něco v těle ctoru, copy ctoru, assignment operatoru a dtoru, a instance takový třídy třeba pak naládovat do nějaké kolekce a sledovat, co se děje (a zkusit si to napřímo i přes nějaký pointer), to by mohlo trochu přispět k získání nějaké intuice. Pokud by se ti nechtělo psát ty smart pointery, tak v pohodě, ale tuhle logovací dummy třídu bych opravdu hodně doporučoval.
Pokud to vyloženě nepotřebuješ, tak bych to nedělal.
Teď to nepotřebuji, ale pokud bych v tom měl psát cokoli složitějšího než „hello world“ tak to potřebovat budu. Nechce se mi psát rovnou větší program a na něm se to teprve učit – přijde mi lepší (na učení) psát malý program, ale stylem, jako by byl trochu větší nebo jako by to byla součást nějakého většího programu.
Začal bych co nejjednodušeji.
Já se tu přece nesnažím reimplementovat EJB, ORM, JAXB, IoC/DI nebo nějaké návrhové vzory z Javy… ale řeším úplně základní věci. Připomíná mi to, jak se tuhle někdo divil, že mám v programu několik #include
a volám nějaké, podle něj zbytečné, funkce – ale já jsem chtěl jen vypsat text na standardní výstup, což považuji za naprosto základní věc. Akorát jsem chtěl, aby se výstup nerozesral, když text bude obsahovat háčky a čárky (což v 21. století taky považuji za základní věc), a jednodušeji to prostě nešlo.
Sčítání integerů nebo předávání hodnot/ukazatelů/referencí do funkcí, to už jsem si vyzkoušel a tohle snad zvládám a vím, jak se to chová, ale to bohužel k napsání nějaké smysluplné aplikace nestačí.
Jestli dává smysl mít ty instance v kolekci napřímo nebo přes pointer, případně přes jaký druh pointeru, to je něco, co si musíš vymyslet sám tak, aby to co nejlépe sedělo na tvůj usecase
To, co jsem v tomhle případě hledal, je tedy asi ta mapa obsahující chytré ukazatele. Jen mi bylo zvláštní, že neexistuje nějaké elegantnější řešení, protože s tímhle se fakt moc dobře nepracuje. Čekal bych něco, co bude kombinovat mapu a chytrý ukazatel v jednom, ale to možná nejde.
Já se tu přece nesnažím reimplementovat EJB, ORM, JAXB, IoC/DI nebo nějaké návrhové vzory z Javy… ale řeším úplně základní věci.Možná seš hustej a já tě zbytečně podceňuju, ale interpret custom assembly-like DSL, jehož příkazy/ISA je možné rekonfigurovat runtime a který má GUI a umí přijímat e-mail mi nepřipadá jako "úplně základní věc"...
To, co jsem v tomhle případě hledal, je tedy asi ta mapa obsahující chytré ukazatele. Jen mi bylo zvláštní, že neexistuje nějaké elegantnější řešení, protože s tímhle se fakt moc dobře nepracuje.Můžeš si definovat nějaké typedefy / aliasy pro smart pointery, které potřebuješ. V jedné větší codebase, kde jsem něco dělal, měli v každé třídě typedef pojmenovaný
ptr
pro smart pointer na tu třídu, ie použití pak bylo FooBar::Ptr
nebo taknějak.
Ale přijde mi to negativní v tom, že to může vést k nadužívání shared_ptr
.
Čekal bych něco, co bude kombinovat mapu a chytrý ukazatel v jednom, ale to možná nejde.Cože? To mi nezní úplně smysluplně. Technicky vzato by to jít mělo - jestli chceš, můžeš si tu mapu podědit na konkrétní typ nebo si vytvořit templatovaný potomek té mapy, který bude pro typ
T
instancovat mapu obsahující shared_ptr<T>
. Nicméně tohle bych pokudmožno nedělal. Můžu se mýlit, ale stále se s těmi shared pointery v mapě nemůžu zbavit dojmu, že se snažíš naroubovat javovský návrh na C++.
BTW: Nemáte někdo zkušenost s tímhle: A garbage collector for C and C++.Nedoporučuju. Boehm GC má špatnou pověst (AFAIK není to moc dobrý GC), navíc s ním to bude tuplem "Java v C++" a nenaučíš se, jak ty věci řešit standardním způsobem...
Nedoporučuju. Boehm GC má špatnou pověst (AFAIK není to moc dobrý GC),Tohle je tezka dojmologie. Nevim, jak v C++, ale v C jsem s BDWGC nejakou dobu intenzivne a pracoval a na zadne problemy, ci propad vykonu oproti beznemu alokatoru jsem nenarazil. V nekterych scenarich, kdy se GC ani nestacil spustit, byly vysledky dokonce lepsi.
navíc s ním to bude tuplem "Java v C++" a nenaučíš se, jak ty věci řešit standardním způsobem...Otazka je, ceho chce dosahnout. Jestli se naucit C++ nebo udelat funkcni aplikaci, ktera resi nejaky konkretni problem.
Tohle je tezka dojmologie. Nevim, jak v C++, ale v C jsem s BDWGC nejakou dobu intenzivne a pracoval a na zadne problemy, ci propad vykonu oproti beznemu alokatoru jsem nenarazil. V nekterych scenarich, kdy se GC ani nestacil spustit, byly vysledky dokonce lepsi.Ok, dobře. Já ten názor četl na jednom fóru, kde se na to někdo ptal.
BTW: Nemáte někdo zkušenost s tímhle: A garbage collector for C and C++.
https://martinfowler.com/books/dsl.html
Máš tu knížku, je tam konkrétní řešení tohoto problému? Nebo to odkazuješ jen, že se tady v diskusi náhodou taky řeší něco jako DSL?
Ve skutečnosti mi nejde o nějaké DSL nebo jazyky – může to být cokoli, filtry e-mailu, obdoba servletů nebo prostě cokoli, co se na základě nějakého klíče (nebo složitějšího mechanismu) vyhledá, předají se tomu nějaká data, ono je to zpracuje a vrátí nebo odešle jinam… a tyhle procesory dat se můžou v čase měnit, můžou vznikat, zanikat.
Nemůžeš mít v té mapě třeba nějaké factory funkce nebo objekty a z nich ty 'procesory' vytvářet?A nerozciloval ses nedavno, ze se v Jave na jednu vec vzdycky vytvori dve tovarny a pet singletonu? Co navrhujes je zbytecny over-engineering (ve vetsine pricetnych programovacich jazyku). Jestli jsem to spravne pochopil, procesor je ,,volatelny objekt'', kteremu se predaji data a on neco vyplivne nebo neco udela. To jestli ma nejaky stav je podruzne a je na jeho zodpovednosti, aby si ten stav korektne udrzoval. To same se tyka pripadne synchronizace.
A nerozciloval ses nedavno, ze se v Jave na jednu vec vzdycky vytvori dve tovarny a pet singletonu?Myslim si, že na opravdové Java enterprise řešení ten můj návrh fakt nemá...
Co navrhujes je zbytecny over-engineering (ve vetsine pricetnych programovacich jazyku). Jestli jsem to spravne pochopil, procesor je ,,volatelny objekt'', kteremu se predaji data a on neco vyplivne nebo neco udela.Tak kdyby to takhle stačilo, tak to mi samozřejmě přijde lepší, nicméně tazatel vyhrožoval, že bude potřeba ty procesory rekonfigurovat a nějak je mazat a znova vyvolávat a kdovíco dále. Je mi to celkem jedno, přijde mi, že stejně nemá cenu to řešit, když nevíme pořádně zadání...
To jestli ma nejaky stav je podruzne a je na jeho zodpovednosti, aby si ten stav korektne udrzoval. To same se tyka pripadne synchronizace.Ve chvíli, kdy se do toho dají vlákna, už mi to podružné nepřijde. IMHO je lepší, když mají vlákna každý svoje vlastní data, která si mohou u sebe mutovat, než když mutují nějaký sdílený data, kde se pak musí řešit zamykání et al. (Samozřejmě ne vždycky to je možný takhle udělat.)
Tak on autor tohoto zapisku udelal - imo - nejlepsi soucasnou cteku rss.Jako, nechci to hejtovat, ale když jsem to zkoušel (když vydal poslední blog o tom), tak to bylo naprosto brutálně nedotažené, při používání se mi to rozpadlo (layout), stahování RSS trvalo asi tak půl hodiny v blokujícím režinmu. Žádné filtrování, žádné scriptování, nic. Neviděl jsem jediný důvod to používat místo inoreaderu. Samozřejmě, jako projekt je to fajn a věřím, že to někam dotáhne, ale momentálně to fakt má k nejlepší čtečce hodně daleko.
$ ldd `which emacs` | grep systemd libsystemd.so.0 => /lib/x86_64-linux-gnu/libsystemd.so.0 (0x00007fe8351ab000)
Jenže kvůli tomu to pak závisí na půlmegabajtové knihovně (a kódu, který je za ní):
$ du /lib/x86_64-linux-gnu/libsystemd.so.0.14.0 524K /lib/x86_64-linux-gnu/libsystemd.so.0.14.0
Tohle je přesně věc, která se mi na systemd nelíbí – je příliš monolitické a jeho rozhraní je IMHO špatně navržené – mělo by být modulární, aby každý mohl záviset jen na tom, co opravdu potřebuje + tam, kde to má smysl, by to měl být otevřený standard, aby totéž rozhraní mohly implementovat i jiné init systémy. Jednotlivé moduly by šlo taky samostatně verzovat, takže když budeš záviset na nějaké základní funkcionalitě, která se moc nemění, tak tě nemusí trápit, že vyšla nová verze systemd, protože to tvoje rozhraní se nemění.
(Možná už to někdo udělal…) dobré by bylo mít nějakou abstrakci (např. pro socket activation), aby to bylo jednoduché stabilní rozhraní, na které by se mohly napojit aplikace. A pak by existovaly implementace/přemostění na různé init systémy – zpočátku klidně jen na ten systemd, ale důležité je, že aplikace by závisela na otevřeném obecném rozhraní jehož implementaci by mohl dodat kdokoli (libovolný init systém nebo třeba nějaký testovací framework).
Ale na druhou stranu, dokud to jde v tom SW lehce vypnout jednym define, tak me to zas tolik netrapi :)
Aspoň, že tak.
On Emacs je sice super, ale pro nektere vetsi zasahy do nej se proste obcas dostanes z elispu az do core veci, co jsou v C a nekdy ne uplne snadno citelnem (Emacs pouziva treba GTK, ale neni to GTK aplikace a podobne veci).To je sice pravda, ale vůči editoru, kde nemůžeš mimo C++ udělat nic je to pořád silný pokrok.
Hlavně to, že je jazyk kompilovaný, není překážkou pro rozšiřitelnost (třetí stranou, formou modulů/pluginů).
Dynamická knihovna se přece dá načíst i za chodu programu, ne?
ze se interaktivne modifikuje primo prostredi...
Tam ale narážíš na problém: kde je hranice mezi rozhraním (které by mělo být stabilní, dokumentované, dlouhodobě podporované…) a interními záležitostmi programu/jádra (ty si jeho autor může měnit a refaktorovat, jak se mu zachce). Když se začneš hrabat ve vnitřnostech programu (dynamický jazyk to přece podporuje) a začneš na nich záviset, tak se ti tvůj plugin/skript může kdykoli bez varování rozsypat. To není zrovna dobrá vlastnost u nástroje, který používáš k práci (a vlastně by mi to vadilo i u hry nebo třeba přehrávače filmů).
Vytvářet další omezeně-konfigurovatelný a omezeně-scriptovatelný editor imho nemá moc smysl
A myslíš, že nejuniverzálnější a nejméně omezené řešení je vždy nejlepší? To můžeš dát uživateli rovnou kompilátor nebo interpret nějakého jazyka a okno, kam jde psát text – zbytek už si dodělá sám.
A myslíš, že nejuniverzálnější a nejméně omezené řešení je vždy nejlepší? To můžeš dát uživateli rovnou kompilátor nebo interpret nějakého jazyka a okno, kam jde psát text – zbytek už si dodělá sám.Myslím si, že ano. Programátorský editor by ti měl poskytnout nějaký druh frameworku. Jednoduchý, jednotný a multiplatformní způsob, jak reagovat na různé eventy, ať již jsou to stisky kláves, nebo třeba označení textu. Způsob jak definovat syntaxe. Všemožné hooky. Vykreslování textu, ale i obrázků. A ten engine na pozadí by měl být rychlý a pokud možno inteligentní, aby zvládl otevřít i 10GB SQL a obarvit v něm syntaxi. Samozřejmě, že neprogramátorský editor tak vůbec fungovat nemusí a je to ok, ale pokud mám něco používat, tak rozhodně už nikdy v životě nechci být omezován fantazií autora; Časová investice do editoru je velká, přitom je to můj primární nástroj, který mi vydělává na živobytí každý den. Pokud se mám přeučit na něco jiného, tak chci abych to mohl upravit, když potřebuji. Editory, které to nenabízí jsou pro mě jen hračky. Tím samozřejmě nechci shazovat autora - je zcela možné, že spoustě lidí se bude editor líbit a bude jim vyhovovat.
Svobodný parametrický CAD? Ten už existuje: SOLVESPACE. Pro začátek by stačilo vylepšovat ten…
BTW: Pracuje se v tom docela dobře a je to i zábava (člověk si tu geometrii užije víc než ve škole). Narážel jsem tam na nějaké nepříjemné problémy, ale to bylo hlavně v UI – nemělo by být tak těžké to upravit. Hlavně když chceš mít víc „vrstev“ nebo vkládat modely z jiných souborů, tak se s tím špatně pracuje (v tomhle je lepší OpenSCAD – i když tam člověk píše zdroják).
jj, funguje to, jednu věc už jsem z toho vytiskl.
Při návrhu něčeho netriviálního jsem měl trochu problém se v tom neztratit, ale jak jsem psal, to je primárně otázka UI a jejich pojetí „vrstev“ (resp. on je to spíš proces, jehož jednotlivé kroky se na model postupně aplikují – v tomhle mi víc vyhovuje, jak řeší kompozici OpenSCAD). Jinak je to ale hodně dobré a je to přesně přístup k modelování, který bych chtěl.
Programátorský editor by ti měl poskytnout nějaký druh frameworku. Jednoduchý, jednotný a multiplatformní způsob, jak reagovat na různé eventy, ať již jsou to stisky kláves, nebo třeba označení textu.
Programátoři jsou sice dost specifická cílová skupina, ale v zásadě mají dost podobné potřeby resp. jde najít nějaký společný základ, na kterém se většina shodne (a ten zbytek si editor dokonfiguruje nebo rozšíří podle svého). On taky ten programátor může chtít programovat svoji aplikaci a ne se vrtat v editoru a vyvíjet si svůj vlastní (když má stejné potřeby jako spousta jiných programátorů a mohli by používat stejný editor).
Způsob jak definovat syntaxe.
Tohle editory běžně mají – a přesto to nejsou jen nějaké frameworky, nad kterými by sis musel editor teprve postavit, ale hotové programy, které můžeš hned používat.
Nicméně definovat si vlastní syntaxi jazyka není úkol pro uživatele editoru, ale pro autora jazyka – což jen v malém zlomku bude tatáž osoba – většina uživatelů si vlastní jazyk definovat nebude.
Zajímavou funkcí je ten Highlighter, o kterém píšu níže – tam nadefinuješ jen regulární výrazy a přiřadíš jim barvy a ono ti to pak zvýrazňuje text – nemusíš definovat celou gramatiku, ale jen pár věcí, co tě zajímá. Přidáš si tam třeba (TODO|FIXME):.*
nebo jiné věci, které chceš mít dobře viditelné. Dobrý kompromis mezi užitečností a jednoduchostí ovládání.
A ten engine na pozadí by měl být rychlý a pokud možno inteligentní, aby zvládl otevřít i 10GB SQL a obarvit v něm syntaxi.
To je prakticky nereálné resp. řešitelné je to jen s obrovskými nároky na paměť a CPU.
Takhle velký soubor si budeš chtít spíš namapovat do paměti než že by sis ho načetl do nějaké proměnné jako běžný obsah textového souboru. To je úplně jiný případ užití. A v té namapované paměti budeš skákat na nějaké adresy. Pokud bys chtěl (správně) zvýraznit syntaxi, tak bys musel parsovat podle dané gramatiky celý soubor od začátku až do místa, které edituješ / prohlížíš. Kdybys to zvýrazňoval od prostředka (třeba jen to, co vidíš na obrazovce), tak to není zvýrazňování syntaxe, ale jen vybraných klíčových slov – to je primitivní a dá se to udělat s minimálními nároky na zdroje, ale bude to dávat chybné výskledky. Ten velký SQL soubor totiž může obsahovat dlouhou textovou hodnotu, která bude obsahovat slova jako SELECT, FROM atd. ale protože jsi ten soubor neprojel od začátku, tak nevíš, že to nejsou klíčová slova, ale text uvnitř apostrofů. U SQL ta textová hodnota většinou nemůže být moc dlouhá, takže tam se začátku výrazu možná nějak dobereš, ale třeba u takového XML omezení délky pro CDATA snad ani není.
…rozhodně už nikdy v životě nechci být omezován fantazií autora; Časová investice do editoru je velká, přitom je to můj primární nástroj, který mi vydělává na živobytí každý den. Pokud se mám přeučit na něco jiného, tak chci abych to mohl upravit, když potřebuji.
Pokud je to svobodný software (což třeba Sublime není) tak se můžeš zapojit do vývoje. Věci užitečné (nebo aspoň neškodlivé) pro většinu uživatelů se můžou dostat do jádra programu nebo základních modulů, věci specifické pro úzkou skupinu lidí můžou být ve volitelných modulech a když bude úplně nejhůř, tak si můžeš udržovat vlastní patch. Ten se ti sice může rozsypat, když autor nekompatibilně překope kód, ale úplně stejným způsobem by se ti rozsypal plugin/skript v dynamickém jazyce, který závisí na vnitřnostech programu (něco si tam šmudlá s jeho objekty, aniž by je autor programu prohlásil za veřejné API a zavázal se tím, že to bude stabilní).
Kdysi se to tu probíralo – někdo by chtěl žít jako počítačový poustevník částečně odstřižený od civilizace, což znamená i malý přísun elektřiny a s tím spojený nevýkonný HW.
Nicméně pokud budu editovat 10 GB soubor, tak to pravděpodobně nebudu dělat interaktivně a už vůbec při tom nebudu řešit nějaké zvýrazňování syntaxe.
Pěkné, přidal jsem do výběru.
Zatím jsem nezkoušel, ale koukal jsem do manuálu – pár otázek a tipů:
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.