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 14:00 | Zajímavý článek

    Byl publikován aktuální přehled vývoje renderovacího jádra webového prohlížeče Servo (Wikipedie).

    Ladislav Hagara | Komentářů: 0
    včera 12:00 | Nová verze

    V programovacím jazyce Go naprogramovaná webová aplikace pro spolupráci na zdrojových kódech pomocí gitu Forgejo byla vydána ve verzi 12.0 (Mastodon). Forgejo je fork Gitei.

    Ladislav Hagara | Komentářů: 0
    17.7. 18:44 | Zajímavý článek

    Nová čísla časopisů od nakladatelství Raspberry Pi zdarma ke čtení: Raspberry Pi Official Magazine 155 (pdf) a Hello World 27 (pdf).

    Ladislav Hagara | Komentářů: 1
    17.7. 16:11 | Nová verze

    Hyprland, tj. kompozitor pro Wayland zaměřený na dláždění okny a zároveň grafické efekty, byl vydán ve verzi 0.50.0. Podrobný přehled novinek na GitHubu.

    Ladislav Hagara | Komentářů: 2
    17.7. 15:55 | Komunita

    Patrick Volkerding oznámil před dvaatřiceti lety vydání Slackware Linuxu 1.00. Slackware Linux byl tenkrát k dispozici na 3,5 palcových disketách. Základní systém byl na 13 disketách. Kdo chtěl grafiku, potřeboval dalších 11 disket. Slackware Linux 1.00 byl postaven na Linuxu .99pl11 Alpha, libc 4.4.1, g++ 2.4.5 a XFree86 1.3.

    Ladislav Hagara | Komentářů: 5
    16.7. 21:22 | IT novinky

    Ministerstvo pro místní rozvoj (MMR) jako první orgán státní správy v Česku spustilo takzvaný „bug bounty“ program pro odhalování bezpečnostních rizik a zranitelných míst ve svých informačních systémech. Za nalezení kritické zranitelnosti nabízí veřejnosti odměnu 1000 eur, v případě vysoké závažnosti je to 500 eur. Program se inspiruje přístupy běžnými v komerčním sektoru nebo ve veřejné sféře v zahraničí.

    Ladislav Hagara | Komentářů: 19
    16.7. 16:22 | IT novinky

    Vláda dne 16. července 2025 schválila návrh nového jednotného vizuálního stylu státní správy. Vytvořilo jej na základě veřejné soutěže studio Najbrt. Náklady na přípravu návrhu a metodiky činily tři miliony korun. Modernizovaný dvouocasý lev vychází z malého státního znaku. Vizuální styl doprovází originální písmo Czechia Sans.

    Ladislav Hagara | Komentářů: 26
    16.7. 15:33 | Upozornění

    Vyhledávač DuckDuckGo je podle webu DownDetector od 2:15 SELČ nedostupný. Opět fungovat začal na několik minut zhruba v 15:15. Další služby nesouvisející přímo s vyhledáváním, jako mapyAI asistent jsou dostupné. Pro některé dotazy během výpadku stále funguje zobrazování například textu z Wikipedie.

    bindiff | Komentářů: 8
    16.7. 13:33 | Bezpečnostní upozornění

    Více než 600 aplikací postavených na PHP frameworku Laravel je zranitelných vůči vzdálenému spuštění libovolného kódu. Útočníci mohou zneužít veřejně uniklé konfigurační klíče APP_KEY (např. z GitHubu). Z více než 260 000 APP_KEY získaných z GitHubu bylo ověřeno, že přes 600 aplikací je zranitelných. Zhruba 63 % úniků pochází z .env souborů, které často obsahují i další citlivé údaje (např. přístupové údaje k databázím nebo cloudovým službám).

    Ladislav Hagara | Komentářů: 5
    16.7. 00:11 | Nová verze

    Open source modální textový editor Helix, inspirovaný editory Vim, Neovim či Kakoune, byl vydán ve verzi 25.07. Přehled novinek se záznamy terminálových sezení v asciinema v oznámení na webu. Detailně v CHANGELOGu na GitHubu.

    Ladislav Hagara | Komentářů: 0
    Jaký je váš oblíbený skriptovací jazyk?
     (59%)
     (27%)
     (7%)
     (3%)
     (0%)
     (1%)
     (4%)
    Celkem 410 hlasů
     Komentářů: 16, poslední 8.6. 21:05
    Rozcestník

    Dotaz: C++ Template a návratový typ

    13.7.2018 21:16 Pavel
    C++ Template a návratový typ
    Přečteno: 2361×
    Zdravím, mám né zrovna šikovně navrženou část aplikace v C++ a pokouším se to zjednodušit - nejspíš pomocí templatů, které jsem ale už dost zapomněl, takže bych tady chtěl poprosit o radu...

    Mam data dost ošlivě uložené ve třídě ze které je získávám jako pole pomocí metod readXY podle datových typů. Původně byly 2, teď už jich je hromada:
    
    Class Data
    {
    public:
    ...
    std::vector<u8> readU8(Info i);
    std::vector<float> readFloat(Info i);
    std::vector<std::vector<float>> readFloatVector(Info i);
    ...
    }
    Ve třídě Info je hromada informací podle kterých ty data získávám + jejich datový typ uložený jako enum class
    
    enum class DatovyTyp : u8 {U8,Float,FloatVector,...}
    class Info
    {
    public:
    ...
    std::string jmeno;
    DatovyTyp typ;
    ...
    }
    
    Celé použití je dost nešikovné, protože když chci získat všechny data a pak je zase dál použít, musím mít IF pro každý datový typ: (navazující metody už jsou teplate nebo přetížené, takže umí pracovat se všemi datovými typy, které potřebuju)
    
    Data d(...);
    for(...)
    {
      Info i(...);
      if(i.typ == DatovyTyp::Float)
      {
        std::vector<float> tmp = d.readFloat(i);
        nějakáPřetíženáFunkceNeboTemplate(tmp,...);
      }
      else if(i.typ == VariableType::U8)
      {
        nějakáPřetíženáFunkceNeboTemplate(d.readU8(i),...);
      }
    }
    
    Použití template ve smyslu:
    
    template <typename T>
        T read(Info i)
    {
    ...
    
    mě sice sjednotí všechny readXY do jedné šablony, ale pořád budu muset mít IF pro každý datový typ
    
    if(i.typ == DatovyTyp::Float)
    {
      std::vector<float> tmp = d.read<float>(i);
      nějakáPřetíženáFunkceNeboTemplate(tmp,...);
    }
    else if(i.typ == VariableType::U8)
    {
      nějakáPřetíženáFunkceNeboTemplate(d.read<u8>(i),...);
    }
    
    Chtěl bych idálně mít nějaký kouzelný template, který vrací datový typ podle toho enum class DatovyTyp - což pokud vím nejde.

    Takže se ptám, jestli existuje nějaká možnost jak uložit informaci o datovém typu tak, abych to potom mohl použít k určení návratového datového typu v template? Zatím jsem nic nenašel a co se pamatuju, tak tohle template neumožňují - existuje nějaká možnost jak to obejít?

    Nebo jak to celé upravit nějak jinak, abych se vyhnul IF pro každý datový typ?

    Díky.

    Odpovědi

    13.7.2018 23:30 MadCatX
    Rozbalit Rozbalit vše Re: C++ Template a návratový typ
    Jestli to chápu správně, potřebuješ se rozhodnout za běhu, jaká data chceš z té třídy Data získat. To se čistě templaty vyřešit nedá, protože templaty v C++ se řeší pouze při překladu. Nějaké runtimové logice s větvením se tedy nevyhneš. Dá se to ale částečně zjednodušit tím, že logiku, která za běhu zjistí požadovaný datový typ a podle toho zavolá příslušnou obsluhu přesuneš do jedné flexibilní funkce. Nějaký nástin, jak na to můžeš najít třeba tady: https://pastebin.com/XUvcSJUr. Vtip je v tom, že to, co se předává dispatcheru jako templatový parameter P lze naimplemetovat libovolně, zatímco dispatcher bude vždy jen jeden.

    Dalo by se to samozřejmě rozšířit i pro případy, že by měl dispatcher něco vracet apod. ale princip by byl stejný...
    13.7.2018 23:46 MadCatX
    Rozbalit Rozbalit vše Re: C++ Template a návratový typ
    Šikovnější verze, která se neomezuje jen na funkci read():

    https://pastebin.com/5GuZk4m5
    16.7.2018 10:32 Pavel
    Rozbalit Rozbalit vše Re: C++ Template a návratový typ
    Díky moc, něco takového jsem hledal... jen jsem doufal v trochu jednodušší použití. Určitě to v nějaké podobě použiju, ale má to bejt zároveň rozhraní knihovny kterou budou používat i lidi pro který je šablona sprostý slovo - takže moc nepředpokládám, že by si někdo implementoval P.

    Po delší době jsem zjistil, kolik jsem toho a zapomněl a jak moc mi ujíždí vlak... každopádně ještě jednou díky.

    16.7.2018 11:59 MadCatX
    Rozbalit Rozbalit vše Re: C++ Template a návratový typ
    P, která s budou používat nejčastěji můžeš implementovat ty jako autor rozhraní s tím, že coder monkey prostě zavolá nějaký wrapper okolo dispatcheru a nebude řešit, co se vevnitř děje. std::variant v kódu není nejspíš proto, že je to věcička až z C++17 a starší překladače to nezbaští.
    16.7.2018 13:19 Pavel
    Rozbalit Rozbalit vše Re: C++ Template a návratový typ
    Ano - přesně tak jsem to myslel - že udělám dvě nejčastější použití a celé to zabalím...

    "std::variant v kódu není nejspíš proto, že je to věcička až z C++17 a starší překladače to nezbaští" ->

    Teď nevím co tím je myšleno... původně se ve třídě Data používal boost::any, který je v boost od 2007 (boost 1.34) stejně jako boost::variant. Spíš jsem se divil, že byl použit any místo variant, který by byl asi vhodnější (má daný výčet povolených typů, do any můžu uložit cokoliv) - ale zas takový rozdíl v nich nevidím. Stejně použití variant / any ať už boost nebo std v tomhle případě nic neřeší - stejně budu znát datový typ, který z toho chci vytáhnout, až za běhu - je jedno, jestli použiju vlastní template nebo std::get<float>(variant) ... jestli mi teda zase něco neuniklo ;-)
    14.7.2018 10:18 Sten
    Rozbalit Rozbalit vše Re: C++ Template a návratový typ
    Jestli to chápu dobře, tak chcete něco jako std::variant? Tam se to řeší přes visitor patern.
    14.7.2018 11:44 MadCatX
    Rozbalit Rozbalit vše Re: C++ Template a návratový typ
    To jsem si původně myslel taky ale z dotazu není jasné, zda obsahuje třída Data data vždy jen jednoho typu nebo zda je možné zavolat d.readFloat() a d.readU8() na jedné instanci té třídy. To by se variantem myslím řešit nedalo. Aspoň trochu flexibilní logika, jak řešit ten druhý případ by mohla vypadat třeba takto:
    #include <iostream>
    #include <vector>
    
    enum class TypeID {
    	String,
    	Float,
    	Integer
    };
    
    template <TypeID>
    struct TypeIdentifier {
    };
    
    template <>
    struct TypeIdentifier<TypeID::String> {
    	typedef std::string type;
    };
    
    template <>
    struct TypeIdentifier<TypeID::Float> {
    	typedef float type;
    };
    
    template <>
    struct TypeIdentifier<TypeID::Integer> {
    	typedef int32_t type;
    };
    
    struct Data {
    	template <typename T>
    	std::vector<T> read();
    };
    
    
    template <>
    std::vector<std::string> Data::read()
    {
    	return std::vector<std::string>{ "Zero", "One", "Two" };
    }
    
    template <>
    std::vector<float> Data::read()
    {
    	return std::vector<float>{ 0.1, 0.2, 0.3 };
    }
    
    template <>
    std::vector<int32_t> Data::read()
    {
    	return std::vector<int32_t>{ 10, 20, 30 };
    }
    
    template <typename T>
    void print(const T &t)
    {
    	for (auto && i : t)
    		std::cout << i << " ";
    	std::cout << "\n";
    }
    
    template <typename T>
    void printReverse(const T &t)
    {
    	for (auto it = t.rbegin(); it != t.rend(); it++)
    		std::cout << *it << " ";
    	std::cout << "\n";
    }
    
    template <template <typename> class P, typename S, typename... Args>
    void dispatcher(const TypeID id, S &s, Args... args)
    {
    	switch (id) {
    	case TypeID::String:
    		P<TypeIdentifier<TypeID::String>::type>::call(s, std::forward<Args>(args)...); break;
    	case TypeID::Float:
    		P<TypeIdentifier<TypeID::Float>::type>::call(s, std::forward<Args>(args)...); break;
    	case TypeID::Integer:
    		P<TypeIdentifier<TypeID::Integer>::type>::call(s, std::forward<Args>(args)...); break;
    	}
    }
    
    template <typename T>
    struct Proc {
    	static void call(Data &d)
    	{
    		auto v = d.read<T>();
    		print(v);
    	}
    };
    
    template <>
    struct Proc<int32_t> {
    	static void call(Data &d)
    	{
    		std::cout << "Specialization for int32_t\n";
    
    		auto v = d.read<int32_t>();
    		print(v);
    	}
    };
    
    template <typename T>
    struct ProcTwo {
    	template <typename... Args>
    	static void call(Data &d, Args ...)
    	{
    		auto v = d.read<T>();
    		printReverse(v);
    	}
    };
    
    template <>
    struct ProcTwo<float> {
    	static void call(Data &d, int i)
    	{
    		std::cout << "Specialization for float: " << i << "\n";
    
    		auto v = d.read<float>();
    		printReverse(v);
    	}
    
    	template <typename... Args>
    	static void call(Data &, Args...)
    	{
    		throw std::runtime_error("Function called with invalid parameters");
    	}
    };
    
    int main()
    {
    	Data d;
    
    	dispatcher<Proc>(TypeID::String, d);
    	dispatcher<Proc>(TypeID::Float, d);
    	dispatcher<Proc>(TypeID::Integer, d);
    
    	dispatcher<ProcTwo>(TypeID::String, d);
    	dispatcher<ProcTwo>(TypeID::Float, d, 66);
    	//dispatcher<ProcTwo>(TypeID::Float, d);    /* Throws at runtime */
    	dispatcher<ProcTwo>(TypeID::Integer, d);
    
    	return 0;
    }
    
    16.7.2018 10:39 Pavel
    Rozbalit Rozbalit vše Re: C++ Template a návratový typ
    Třída Data právě obsahuje vždy data víc typů... původně byly interně uloženy jako boost::any (už se nepamatuju proč se nepoužil variant), ale kvůli rychlosti a velikosti se to změnilo na dost ošlivej bastl. I kdyby se použil std::variant, tak by to zrovna v tomhle ničemu nepomohlo (jinde jo, takže se o tom čas od času uvažuje)...
    14.7.2018 12:29 Kit | skóre: 45 | Brno
    Rozbalit Rozbalit vše Re: C++ Template a návratový typ
    Co znamená "získat data ze třídy"? Co takhle raději místo toho "zpracovat data v objektu"? Tím se hromada zmíněných problémů vyřeší, protože ify nebudou potřebné.
    Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
    14.7.2018 22:02 zvol
    Rozbalit Rozbalit vše Re: C++ Template a návratový typ
    Můžete tím enumem "indexovat" variadický template.

    ideone.com/w1CLnF

    Ukázka:
    template<int N, class Head, class... Tail>
    struct Dispatch {
      static void dispatch(const Info& i, const Data& d) {
        if (i.typ == N)
          perform<Head>(i, d);
        else
          Dispatch<N+1, Tail...>::dispatch(i, d);
      }
    };
    

    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.