I migrate a code from C++11 to C++17. In that code I do something like this (non-valid) code:
template <typename... Ts>
std::vector<std::size_t> store_types()
{
std::vector<std::size_t> t;
for(typename T : Ts)
t.push_back(typeid(T).hash_code());
return t;
}
For the moment, my implementation is the following:
template <typename Unused>
void add_types_in(std::vector<std::size_t>&)
{}
template <typename Unused, typename First, typename... Others>
void add_types_in(std::vector<std::size_t>& t)
{
t.push_back(typeid(First).hash_code());
add_types_in<Unused, Others...>(t);
}
template <typename... Ts>
std::vector<std::size_t> store_types()
{
std::vector<std::size_t> t;
add_types_in<void*, Ts...>(t);
return t;
}
I see a lot a variadic functionalities in C++17, but there is a lot of things I don't understand yet. Is there something more elegant (aka more "one-line") in C++17 than my implementation ? Maybe something similar to fold expressions ?
std::vector
can be initialized with a list of values so you can just expand the pack directly in a braced-init-list like:
template <typename... Ts>
std::vector<std::size_t> store_types()
{
return { typeid(Ts).hash_code()... };
}
If you want to avoid dynamic allocation, you can switch to use a std::array
like:
// C++11 or 14
template <typename... Ts>
auto store_types() -> std::array<std::size_t, sizeof...(Ts)>
{
return { typeid(Ts).hash_code()... };
}
// or
// C++17
template <typename... Ts>
auto store_types()
{
return std::array{ typeid(Ts).hash_code()... };
}