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 15:55 | Pozvánky

Spolek OpenAlt zve příznivce otevřených řešení a přístupu na 156. brněnský sraz, který proběhne v pátek 21. září od 18:00 v restauraci Na Purkyňce na adrese Purkyňova 80.

Ladislav Hagara | Komentářů: 0
dnes 13:22 | Nová verze

Alan Griffiths z Canonicalu oznámil vydání verze 1.0.0 display serveru Mir (GitHub, Wikipedie). Mir byl představen v březnu 2013 jako náhrada X serveru a alternativa k Waylandu. Dnes Mir běží nad Waylandem a cílen je na internet věcí (IoT).

Ladislav Hagara | Komentářů: 0
včera 22:00 | Nasazení Linuxu
Stabilní aktualizace Chrome OS 69 (resp. Chromium OS), konkrétně 69.0.3497.95, přináší mj. podporu linuxových aplikací. Implementována je pomocí virtualizace, a proto je tato funkce také omezena na zařízení s dostatkem paměti a podporou hardwarové akcelerace, tudíž nejsou podporovány chromebooky s 32bitovými architekturami ARM, či Intel Bay Trail (tzn. bez Intel VT-x).
Fluttershy, yay! | Komentářů: 3
včera 21:32 | Zajímavý projekt
Došlo k uvolnění linuxové distribuce CLIP OS, vyvíjené francouzským úřadem pro kybernetickou bezpečnost ANSSI, jako open source. Vznikla za účelem nasazení v úřadech, kde je potřeba omezit přístup k důvěrným datům. Je založená na Gentoo.
Fluttershy, yay! | Komentářů: 0
včera 16:00 | Komerce

Zjistěte více o bezpečné a flexibilní architektuře v cloudu! IBM Cloud poskytuje bezpečné úložiště pro Vaše obchodní data s možností škálovatelnosti a flexibilitou ukládání dat. Zároveň nabízí prostředky pro jejich analýzu, vizualizaci, reporting a podporu rozhodování.

… více »
Fluttershy, yay! | Komentářů: 12
včera 12:22 | Nová verze

V dubnu letošního roku Mozilla představila webový prohlížeč pro rozšířenou a virtuální realitu Firefox Reality (GitHub). V úterý oznámila vydání verze 1.0. Ukázka na YouTube. Firefox Reality je k dispozici pro Viveport, Oculus a Daydream.

Ladislav Hagara | Komentářů: 2
včera 12:00 | Komunita

V srpnu loňského roku společnost Oracle oznámila, že Java EE (Enterprise Edition) bude uvolněna jako open source. O měsíc později bylo rozhodnuto, že tato open source Java EE bude přejmenována a předána Eclipse Foundation. Nové jméno bylo oznámeno v únoru letošního roku. Z Java EE se stala Jakarta EE. Eclipse Foundation včera oznámila dosažení dalšího milníku. Zdrojové kódy aplikačního serveru GlassFish jsou již k dispozici v git repozitářích Eclipse Foundation (GitHub).

Ladislav Hagara | Komentářů: 0
19.9. 23:55 | Komunita

LTS (Long Term Support) podpora Ubuntu 12.04 LTS (Precise Pangolin) skončila po 5 letech od jeho vydání, tj. v dubnu 2017. V březnu 2017 ale Canonical představil placenou ESM (Extended Security Maintenance) podporu, díky které je Ubuntu 12.04 podporováno do dubna 2020. Dnes Canonical potvrdil ESM podporu také pro Ubuntu 14.04 LTS (Trusty Tahr), jehož LTS podpora skončí v dubnu 2019.

Ladislav Hagara | Komentářů: 0
19.9. 15:00 | Nová verze

Byla vydána verze 3.0.0 frameworku pro vývoj multiplatformních desktopových aplikací pomocí HTML, CSS a JavaScriptu Electron (YouTube, GitHub). Electron byl původně vyvíjen pro editor Atom pod názvem Atom Shell. Dnes je na Electronu postavena celá řada dalších aplikací.

Ladislav Hagara | Komentářů: 0
19.9. 14:44 | Nová verze

Po půl roce vývoje od vydání verze 6.0.0 byla vydána verze 7.0.0 překladačové infrastruktury LLVM (Wikipedie). Přehled novinek v poznámkách k vydání: LLVM, Clang, clang-tools-extra a LLD.

Ladislav Hagara | Komentářů: 0
Na optické médium (CD, DVD, BD aj.) jsem naposledy vypaloval(a) data před méně než
 (13%)
 (14%)
 (20%)
 (23%)
 (25%)
 (4%)
 (1%)
Celkem 382 hlasů
 Komentářů: 33, poslední 16.9. 11:55
Rozcestník

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

13.7. 21:16 Pavel
C++ Template a návratový typ
Přečteno: 1711×
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. 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. 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. 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. 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. 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. 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. 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. 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. 12:29 Kit | skóre: 42 | 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. 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.