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í
×
    dnes 10:00 | Komunita

    V Brně na FIT VUT probíhá třídenní open source komunitní konference DevConf.CZ 2025. Vstup je zdarma, nutná je ale registrace. Na programu je celá řada zajímavých přednášek, lightning talků, meetupů a workshopů. Přednášky lze sledovat i online na YouTube kanálu konference. Aktuální dění lze sledovat na Matrixu, 𝕏 nebo Mastodonu.

    Ladislav Hagara | Komentářů: 0
    dnes 09:44 | IT novinky

    Vyloučení technologií, které by mohly představovat bezpečnostní riziko pro stát, má umožnit zákon o kybernetické bezpečnosti, který včera Senát schválil spolu s novelami navazujících právních předpisů. Norma, kterou nyní dostane k podpisu prezident, počítá rovněž s prověřováním dodavatelů technologií pro stát. Normy mají nabýt účinnosti od třetího měsíce po jejich vyhlášení ve Sbírce zákonů.

    Ladislav Hagara | Komentářů: 7
    dnes 01:11 | Nová verze

    Open source platforma Home Assistant (Demo, GitHub, Wikipedie) pro monitorování a řízení inteligentní domácnosti byla vydána v nové verzi 2025.6.

    Ladislav Hagara | Komentářů: 0
    dnes 00:55 | Nová verze

    Po Red Hat Enterprise Linuxu a AlmaLinuxu byl v nové stabilní verzi 10.0 vydán také Rocky Linux. Přehled novinek v poznámkách k vydání.

    Ladislav Hagara | Komentářů: 0
    včera 22:55 | Nová verze

    Bylo vydáno Eclipse IDE 2025-06 aneb Eclipse 4.36. Představení novinek tohoto integrovaného vývojového prostředí také na YouTube.

    Ladislav Hagara | Komentářů: 0
    včera 22:33 | IT novinky

    Americká filmová studia Walt Disney a Universal Pictures podala žalobu na provozovatele populárního generátoru obrázků pomocí umělé inteligence (AI) Midjourney. Zdůvodňují to údajným porušováním autorských práv. V žalobě podané u federálního soudu v Los Angeles označují firmu za „bezednou jámu plagiátorství“, neboť podle nich bez povolení bezostyšně kopíruje a šíří postavy z filmů jako Star Wars, Ledové království nebo Já, padouch, aniž by do nich investovala jediný cent.

    Ladislav Hagara | Komentářů: 1
    včera 18:33 | IT novinky

    Ultra Ethernet Consortium (UEC), jehož cílem je optimalizace a další vývoj Ethernetu s důrazem na rostoucí síťové požadavky AI a HPC, vydalo specifikaci Ultra Ethernet 1.0 (pdf, YouTube).

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

    Francouzský prezident Emmanuel Macron chce zakázat přístup na sociální sítě pro děti do 15 let. Francie podle něj tento krok udělá sama do několika měsíců, i pokud se na něm neshodnou další státy Evropské unie. Reaguje tak na úterní vraždu vychovatelky, kterou ve východofrancouzském městě Nogent pobodal 14letý mladík. Jednotlivé sociální sítě podle něj mají možnost věk ověřit a vymáhat zákaz pomocí systémů na rozpoznávání tváří.

    Ladislav Hagara | Komentářů: 9
    včera 05:11 | IT novinky

    Byl aktualizován seznam 500 nejvýkonnějších superpočítačů na světě TOP500. Nejvýkonnějším superpočítačem zůstává El Capitan od HPE (Cray) s výkonem 1,742 exaFLOPS. Druhý Frontier má výkon 1,353 exaFLOPS. Třetí Aurora má výkon 1,012 exaFLOPS. Nejvýkonnější český počítač C24 klesl na 165 místo. Karolina, GPU partition klesla na 195. místo a Karolina, CPU partition na 421. místo. Další přehledy a statistiky na stránkách projektu.

    Ladislav Hagara | Komentářů: 0
    10.6. 22:33 | Nová verze

    Oficiálně byl vydán Android 16. Detaily na blogu a stránkách věnovaných vývojářům.

    Ladislav Hagara | Komentářů: 5
    Jaký je váš oblíbený skriptovací jazyk?
     (55%)
     (31%)
     (7%)
     (2%)
     (0%)
     (1%)
     (3%)
    Celkem 254 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.