abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
    včera 16:11 | Bezpečnostní upozornění

    V jádře Linux byla nalezena a v upstreamu již byla opravena kritická zranitelnost GhostLock aneb CVE-2026-43499. Lokálnímu uživateli umožňuje získat práva roota a také obejít kontejnerovou izolaci. Zranitelnost existovala v Linuxu 15 let, tj. od roku 2011, od Linuxu verze 2.6.39.

    Ladislav Hagara | Komentářů: 2
    včera 13:55 | IT novinky

    Evropská komise předběžně shledala, že návykový design aplikací Instagram a Facebook od americké společnosti Meta porušuje unijní nařízení o digitálních službách (DSA). Návykový design zahrnuje například takzvané nekonečné posouvání, automatické přehrávání videí, tzv. push notifikace, kdy aplikace uživatele vybízí k návratu do jejího prostředí, či vysoce personalizovaný algoritmus, který rychle pozná, co uživatele baví a snaží

    … více »
    Ladislav Hagara | Komentářů: 3
    včera 12:11 | Nová verze

    Byla vydána verze 1.97.0 programovacího jazyka Rust (Wikipedie). Podrobnosti v poznámkách k vydání. Vyzkoušet Rust lze například na stránce Rust by Example.

    Ladislav Hagara | Komentářů: 0
    včera 05:00 | IT novinky

    Švýcarská společnost Punkt. má nově v nabídce telefon Punkt. MC03. Telefon byl navržen ve Švýcarsku s důrazem na soukromí a digitální suverenitu a vyroben v Německu. V telefonu běží operační systém AphyOS (Apostrophy OS) založený na AOSP (Android Open Source Project) 15. Cena telefonu je 745 eur.

    Ladislav Hagara | Komentářů: 14
    včera 04:44 | Nová verze

    TypeScript (Wikipedie), tj. JavaScript rozšířený o statické typování a další atributy, byl vydán v nové verzi 7.0. Kompilátor byl kvůli výkonu přepsán z TypeScriptu do Go.

    Ladislav Hagara | Komentářů: 0
    9.7. 17:00 | IT novinky

    Europarlament podpořil pozměněnou verzi výjimky známé jako „chat control 1.0“ umožňující firmám skenovat soukromou komunikaci na internetu kvůli ochraně dětí před zneužitím. Pozměňovací návrhy přijaté europoslanci však počítají s tím, že z výjimky bude vyřazena šifrovaná komunikace. Výjimka přestala platit začátkem dubna poté, co se Evropský parlament a Rada EU nedokázaly shodnout na jejím prodloužení. Rada následně přijala

    … více »
    Ladislav Hagara | Komentářů: 12
    9.7. 04:44 | Bezpečnostní upozornění

    Nejnovější X.Org X server 21.1.24 a Xwayland 24.1.13 řeší 2 bezpečnostní chyby.

    Ladislav Hagara | Komentářů: 0
    9.7. 04:22 | Komunita

    Clement "Clem" Lefebvre publikoval souhrn dění v Linux Mintu za červen 2026. Vypíchnuta je vylepšená podpora Waylandu. Už není považována za experimentální. V příští verzi Linux Mintu, plánována je na Vánoce, bude běh Cinnamonu plně podporován na X11 i Waylandu. V květnu na vývoj Linux Mintu přispělo 611 dárců celkovou částkou 19 612 dolarů. Dalších 2 326 patronů přispělo na Patreonu celkovou částkou 5 334 dolarů.

    Ladislav Hagara | Komentářů: 4
    9.7. 04:00 | Bezpečnostní upozornění

    V Linuxu v KVM byla nalezena a v upstreamu již byla opravena kritická zranitelnost Januscape aneb CVE-2026-53359. Root na hostovaném počítači (virtuální stroj) může obejít izolaci a získat plnou kontrolu nad hostitelským systémem (DoS útok nebo vzdálené spuštění kódu s právy roota). Na obou hlavních architekturách – Intel i AMD. Zranitelnost v Linuxu existovala téměř 16 let (od srpna 2010 do června 2026).

    Ladislav Hagara | Komentářů: 0
    8.7. 19:44 | IT novinky

    Tribunál Soudního dvora Evropské unie dnes zamítl několik žalob, v nichž se americká společnost Apple ohrazovala proti pravidlům fungování velkých technologických společností na unijním trhu. Applu se nelíbilo, že jeho obchod s aplikacemi a operační systém iOS mají podléhat přísnějším povinnostem jen proto, že Brusel firmu považuje za takzvaného gatekeepera, tedy strážce přístupu.

    Ladislav Hagara | Komentářů: 2
    Které desktopové prostředí na Linuxu používáte?
     (10%)
     (7%)
     (2%)
     (17%)
     (31%)
     (4%)
     (6%)
     (2%)
     (16%)
     (25%)
    Celkem 2088 hlasů
     Komentářů: 30, poslední 3.4. 20:20
    Rozcestník


    Dotaz: C++ a volání stejné metody na seznamu objektů

    xkucf03 avatar 12.6.2021 15:49 xkucf03 | skóre: 50 | blog: xkucf03
    C++ a volání stejné metody na seznamu objektů
    Přečteno: 907×

    Řeším takový návrhový problém a hledám elegantní řešení v C++.

    Obecně jde o to, že mám třídu (např. parser), jejíž instance přijímá události (někdo volá její metody), nějak je zpracovává a výsledky předává dál – volá metody jiného objektu (handler). Těch handlerů může být víc, implementují stejné rozhraní a uživatel je registruje před začátkem zpracování pomocí metody addHandler().

    Napadá mě několik možností:

    • Metoda addHandler() přidá handler do kolekce a pak budu místo handler->metoda() volat for (auto handler : handlers) handler->metoda() a tím se událost rozešle všem.
    • Metoda addHandler() nebude v parseruparser bude sám schopný pracovat jen s jedním handlerem. Pokud jich bude potřeba víc, vytvoří se proxy handler, který bude implementovat stejné rozhraní a postará se o rozeslání všem stejným způsobem jako v předchozím bodě.
    • Makra a/nebo šablony, které usnadní zápis výše popsaných řešení.
    • Generátor kódu, který bude mít na vstupu definici rozhraní a na výstupu proxy handler.

    Ten handler může mít třeba deset metod, takže se mi to úplně nechce psát všechno ručně, navíc tenhle problém budu asi řešit opakovaně. Časem bych možná chtěl nějak lépe ošetřovat chyby (např. když by jeden handler vyhazoval výjimku, tak aby zpracování dat v ostatních pokračovalo dál a chyba se nějak zpracovala až na konci), ale pro začátek to může být tak, že první vyhozená výjimka zastaví všechno a zpracování skončí.

    Přijde mi, že tohle musí být docela obvyklá úloha, snad i návrhový vzor nebo idiom… tak se mi nechce vynalézat kolo. Jak tohle řešíte vy?

    P.S. To řešení pomocí maker může vypadat takhle:

    #define handler for (auto ___h : handlers) ___h
    
    handler->metoda0();
    handler->metoda1(a, b);
    handler->metoda2(a, b, c);
    ...
    handler->metoda9(x);
    

    Což tak nějak s minimem úsilí řeší tenhle problém, ale moc nadšený z toho nejsem.

    P.P.S. Případně takhle může vypadat kombinace toho makra a proxy:

    class XYZContentHandler {
    public:
    
    	virtual void abc();
    	virtual void def(int a);
    	virtual void ghi(int a, int b);
    
    };
    
    class XYZContentHandlerProxy : public XYZContentHandler {
    private:
    	std::vector<std::shared_ptr<XYZContentHandler>> handlers;
    public:
    
    	void addHandler(std::shared_ptr<XYZContentHandler> handler) {
    		handlers.push_back(handler);
    	}
    
    #define handler for (auto ___h : handlers) ___h
    
    	void abc() override { handler->abc(); }
    	void def(int a) override { handler->def(a); }
    	void ghi(int a, int b) override { handler->ghi(a,b); }
    
    #undef handler
    
    };

    Ale nejradši bych se zbavil toho ručně psaného kódu (proxy) a řešil to nějak obecně, genericky.

    Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-DK, Relational pipes

    Odpovědi

    12.6.2021 23:04 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: C++ a volání stejné metody na seznamu objektů
    #include <iostream>
    #include <memory>
    #include <vector>
    
    using std::vector;
    using std::shared_ptr;
    using std::make_shared;
    using std::cerr;
    using std::endl;
    using std::forward;
    
    struct ContentHandler {
        virtual void handle_a(int x) = 0;
        virtual void handle_b(int x, int y) = 0;
        virtual void handle_c() = 0;
    };
    
    struct Foo: ContentHandler {
        virtual void handle_a(int x) { cerr << "Foo::handle_a(" << x << ")" << endl; }
        virtual void handle_b(int x, int y) { cerr << "Foo::handle_b(" << x << ", " << y << ")" << endl; }
        virtual void handle_c() { cerr << "Foo::handle_c()" << endl; }
    };
    
    struct Bar: ContentHandler {
        virtual void handle_a(int x) { cerr << "Bar::handle_a(" << x << ")" << endl; }
        virtual void handle_b(int x, int y) { cerr << "Bar::handle_b(" << x << ", " << y << ")" << endl; }
        virtual void handle_c() { cerr << "Bar::handle_c()" << endl; }
    };
    
    template <class R, class T, class ...Args>
    void handle_fanout(vector<shared_ptr<T>>& handlers, R (T::*func)(Args...), Args &&... args) {
        cerr << "Fanout to " << handlers.size() << " handlers:" << endl;
        for (auto& handler : handlers) {
            ((*handler).*func)(forward<Args>(args)...);
        }
    }
    
    int main() {
        vector<shared_ptr<ContentHandler>> handlers;
        handlers.push_back(make_shared<Foo>());
        handlers.push_back(make_shared<Bar>());
    
        handle_fanout(handlers, &ContentHandler::handle_a, 3);
        handle_fanout(handlers, &ContentHandler::handle_b, 42, 9001);
        handle_fanout(handlers, &ContentHandler::handle_c);
    }
    
    Je to trochu naprasené... předávání reference na vector by se asi správně mělo nahradit nějakým range nebo po staru párem iterátorů nebo podobně, ale nechtělo se mi to už řešit...
    14.6.2021 12:58 jhnz
    Rozbalit Rozbalit vše Re: C++ a volání stejné metody na seznamu objektů
    Vyjimky by se teoreticky mohly ukladat pres magii s https://en.cppreference.com/w/cpp/error/current_exception

    Nebo nejak ve stylu std::promise::set_exception
    14.6.2021 18:09 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: C++ a volání stejné metody na seznamu objektů
    Spíš bych definoval nějakou výjimku, která by byla součástí API pro ty handlery, a nechal bych je házet jen tu výjimku nebo odvozené, s tim, že by měly implementovat kopírování. Tj. to volání by se obalilo try-catch a chycené výjimky by se někam vykopírovaly pro další zpracování.

    Ale ošklivé to asi bude tak jako tak, výjimky jsou zkrátka zlo :-)
    14.6.2021 17:26 Kit | skóre: 46 | Brno
    Rozbalit Rozbalit vše Re: C++ a volání stejné metody na seznamu objektů
    Vzor Observer.
    Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
    xkucf03 avatar 14.6.2021 18:42 xkucf03 | skóre: 50 | blog: xkucf03
    Rozbalit Rozbalit vše Re: C++ a volání stejné metody na seznamu objektů – metaprogramování

    Ano, ale otázka je, jak to elegantně implementovat s minimem ručně psaného kódu (proxy) nebo for cyklů rozesetých všude možně. Např. v Javě bych to uměl udělat pomocí reflexe nebo anotací a anotačního procesoru. V jazycích s hygienickými makry si zase dovedu představit elegantní řešení založené na úpravě/generování AST.

    Pokud bych omezil počet metod a všechno posílal přes jednu, tak si asi jen ušetřím práci na jednom místě a přidělám práci jinde. Místo prostého volání metod s 0 až N parametry by se musely vytvářet a předávat objekty. Jako API mi to nepřijde moc intuitivní – ten, kdo to bude volat, tak bude řešit otázku, jaké objekty tam může posílat a kde je má vzít (asi v nějaké továrně…) a ten, kdo bude ty události zpracovávat, bude zase řešit otázku, jaké všechny typy mu můžou přijít a jestli to je konečná množina… – místo toho, aby se člověk jednoduše podíval, jaké metody dané rozhraní obsahuje. A když bychom chtěli oddělit API a SPI, tak to bude taky asi horší (tohle zatím neřeším, protože je to jen interní třída, ne nějaké veřejné rozhraní, které by používal a implementoval někdo cizí).

    V C++ se tomu zatím nejvíc blíží to Kralykovo řešení, ale taky to není ono – minimálně proto, že psát handle_fanout(handlers, &ContentHandler::handle_a, 3) je výrazně otravnější než psát proxy.handle_a(3) nemluvě o napovídání parametrů v IDE, které si s tím neporadí (ale aspoň kompilátor ty parametry zkontroluje a upozorní na chybu).

    Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-DK, Relational pipes
    14.6.2021 20:19 Kit | skóre: 46 | Brno
    Rozbalit Rozbalit vše Re: C++ a volání stejné metody na seznamu objektů – metaprogramování
    Místo reflexe bych využil polymorfismu a místo různých parametrů DI kontejner. Ty handlery nemusí mít implementovány všechny metody, zbytek mohou podědit. Cyklus bych měl jen jeden v tom Observeru, který by prošel konktétní metodu u všech abonentů.

    Rodičovské metody by mohly být prázdné - vždy by se zpracovaly jen metody, které jsou implementovány v potomcích.
    Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
    2.7.2021 00:43 Jardík
    Rozbalit Rozbalit vše Re: C++ a volání stejné metody na seznamu objektů
    Bez makra:
    class XYZContentHandler {
    public:
        virtual ~XYZContentHandler() {}
        virtual void abc();
        virtual void def(int a);
        virtual void ghi(int a, int b);
    };
     
    class XYZContentHandlerProxy : public XYZContentHandler {
    private:
        std::vector<std::shared_ptr<XYZContentHandler>> handlers;
    public:
     
        void addHandler(std::shared_ptr<XYZContentHandler> handler) {
            handlers.push_back(handler);
        }
    
        template<typename Func, typename... Args>
        void handler_foreach(Func func, Args&&... args)
        {
            for (auto& h : handlers)
            {
                try {
                    (h.get()->*func)(args...); // umyslne bez std::forward, nechceme, aby potom funkce udelala move z argumentu a rozbila tak dalsi handler
                }
                catch (...) { /* sezer vyjimku */ }
            }
        }
     
        void abc() override { handler_foreach(&XYZContentHandler::abc); }
        void def(int a) override { handler_foreach(&XYZContentHandler::def, a); }
        void ghi(int a, int b) override { handler_foreach(&XYZContentHandler::ghi, a, b); }
     
    };
    
    2.7.2021 00:48 Jardík
    Rozbalit Rozbalit vše Re: C++ a volání stejné metody na seznamu objektů
    A nezapomeň na ten virtuální dtor, jinak si říkáš o problémy s destrukcí!!
    2.7.2021 00:50 Jardík
    Rozbalit Rozbalit vše Re: C++ a volání stejné metody na seznamu objektů
    Koukám teď, že králík dal skoro to samé, a ještě je ta diskuse stará. Tak nic :-)
    2.7.2021 10:05 kralyk z abclinuxu | skóre: 29 | blog:
    Rozbalit Rozbalit vše Re: C++ a volání stejné metody na seznamu objektů
    To nevadí, poznámka o vyhození forwardu je dobrá a ta o virtuálním d-toru taky ;-)
    xkucf03 avatar 3.7.2021 19:07 xkucf03 | skóre: 50 | blog: xkucf03
    Rozbalit Rozbalit vše Re: C++ a volání stejné metody na seznamu objektů

    Díky. Nahradil jsem tím to makro a přesunul to do znovupoužitelné třídy ProxyVector.

    Pořád mi trochu vadí, že tam musím vyjmenovat všechny ty metody, které se mají přeposílat, ale to asi jinak nejde (bez nějakého generování kódu).

    Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-DK, Relational pipes

    Založit nové vláknoNahoru

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.