Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: fortran1986 07. 08. 2021, 01:17:16
-
template <typename... Args>
class PackClass
{
private:
std::tuple<Args...> values;
public:
PackClass(Args&& ...args) :
values(args...)
{
}
template <typename T>
PackClass<Args..., T> Append(T value)
{
return PackClass<Args..., T>(/* riešenie problému */...);
}
};
Dobrý deň prajem, chcel by som mať šablónu triedy, kde do konštruktora chcem mať možnosť nainjektovať argumenty hociakého typu. Tie argumenty, by sa niekam uložili v (mojom prípade je to tuple, ale kludne sa môžu uložiť hocikam inam) a po zavolaní metódy Append by sa vytvorila rovnaká trieda, do ktorej by sa cez konštruktor pridali uložené hodnoty a zároveň by sa k nim na koniec pridala ďalšia hodnota a spolu s hodnotou by sa dosadil ďalší typ medzi template parametre. Robím si fluent interface do ktrého chcem vkladať lambdy (std::function) rôznych typov a na záver ich všetky aplikovať na nejakú hodnotu, ale žiaľ robím to na platforme kde nemám k dispozícii RTTI* ani C++ 20 (mám len 17ku) takže musím sa trochu uskromniť. V mojom prídklade je problém na treťom riadku od spodu kde sa snažím dosadiť tuple, ale neviem ako ho skonvertovať na parametre konštruktoru a pridať tam ďalší paramter
-
Co třeba něco takového?
#include <any>
#include <vector>
class PackClass
{
private:
std::vector<std::any> m_values;
public:
template <typename... Args>
PackClass(Args&& ...args)
:m_values(args...)
{
}
template<typename T>
PackClass(std::vector<std::any> values, T value)
:m_values(std::move(values))
{
m_values.emplace_back(value);
}
template<typename T>
PackClass Append(T value) const
{
return PackClass(m_values, value);
}
};
-
Google je tvůj kamarád:
https://stackoverflow.com/questions/687490/how-do-i-expand-a-tuple-into-variadic-template-functions-arguments
-
Co třeba něco takového?
...
Ďakujem za príklad dosť mi pomohol, keďže v pokročilejšom používaní šablón zatiaľ vôbec nie som doma, ale trošku som ho upravil pre svoje potreby:
#include <iostream>
#include <vector>
#include <utility>
#if __has_include(<any>)
#include <any>
using any = std::any;
#elif __has_include(<experimental/any>)
#include <experimental/any>
using any = std::experimental::any;
#else
static_assert(false, "The std::any type is required");
#endif
template <typename... Args>
class PackClass
{
private:
std::vector<any> m_values;
public:
PackClass(Args&& ...args) :
m_values{ args... }
{
}
template<typename T>
PackClass(std::vector<any> values, T value) :
m_values(
std::move(values)
)
{
m_values.emplace_back(
value
);
}
template<typename T>
PackClass<Args..., T> Append(T value) const
{
return PackClass<Args..., T>(
m_values,
value
);
}
size_t Count() const
{
return m_values.size();
}
std::vector<any> ToVector() const
{
return m_values;
}
auto Fetch()
{
}
};
int main()
{
auto object = PackClass{ 3, std::string("TestString"), 'c' };
auto obj = object.Append(3.5);
std::cout << obj.Count() << std::endl;
auto lastItem = std::any_cast<double>(obj.ToVector()[obj.Count() - 1]);
std::cout << "Test: " << lastItem << std::endl;
//auto value = obj.Fetch();
return 0;
}
- Parameter pack som premiestnil nad classu keďže typovú informáciu budem potrebovať aj pri spracovaní uložených typov
- V prvom konštruktore pri m_values som vymenil () za {} nakoľko s tými pôvodnými zátvorkami to nešlo skompilovať ani Clangom (verzia C++ 17) ani MSVC (verzia C++ 17)
- Teraz budem musieť vyriešiť ešte jeden problém: nejako pomocou fold expressions, prejsť typy parameter packu. Následne hodnotu typu std::any pomocou std::any_cast<cleovy_typ> musím skonvertovať na správny typ. A keďže na cielovej platforme nemám k dispozícii RTTI bohužiaľ nemôžem typy porovnávať takto: if (m_values.type() == typeid(nejakyTyp)) budem tie typy musieť získať nejako cez compiler. S tým teraz bojujem. Asi by som si mal objednať nejakú knihu pokročilom používaní šablón, type traitov a metaprogramovaní v C++, lebo toto je momentálne oblasť C++ v ktorej ešte nemám jasno.
Google je tvůj kamarád:
https://stackoverflow.com/questions/687490/how-do-i-expand-a-tuple-into-variadic-template-functions-arguments
Vďaka za odkaz pozriem. Ja som tých prelúskal, už dosť veľa ale priznávam sa bez mučenia že v metaprogramovaní v C++ mám veľké rezervy. Zatiaľ sa to učím googlením a metódou pokus omyl. Templaty sú omnoho ďalej ako generics na ktoré som zvyknutý z vyšších jazykov.
-
Ještě můžeš zvážít std::variant místo std::any (pokud je předem známá množina typů, které tam můžou být) a pak použít std::visit.
-
Nic nezvažuj, jdeš na to dobře, jen je potřeba pochopit co přesně potřebuješ a jak toho docílit. Já bych typování za každou cenu zachoval v tomto případě.
-
Ahojte, any ani variant som nakoniec nepoužil, prepísal som to na tuple a po niekoľko hodinovom googlení a pozeraní príkladov, som sa dopracoval k tomuto riešeniu:
https://pastebin.com/adVfRz8k
Ešte to upravím. walkValues bude niečo spracovávať a spolu s Fetch() bude vracať hodnotu, v reálnom kóde budem do tuple ukladať funkcie.