Reputation: 1187
I have a class that holds a map of Collection<T>
, which is cast into a void*
for storage purposes.
Each Collection<T>
can hold an array of IDs, and I want to provide some variadic template magic to be able to tell if some ID exists in some grouping of Collection<T>
. I'm just not sure how to go about it, after looking over some examples there is something that I am missing.
template<typename T>
class A {
public:
void add_id(int id) {
ids.emplace_back(id);
}
bool has(int id) {
return std::find(ids.begin(), ids.end(), id) != ids.end();
}
private:
std::vector<int> ids {};
};
class Collection {
public:
template<typename T>
void insert(T* item) {
items.insert({std::type_index(typeid(T)), reinterpret_cast<void*>(item)});
}
template<typename T>
bool contains(int id) {
return reinterpret_cast<T*>(items[std::type_index(typeid(T))])->has(id);
}
template<typename T>
bool does_have(int id) {
return contains<T>(id);
}
template<typename First, typename... Rest>
bool does_have(int id) {
return contains<First>(id) && does_have<Rest...>(id);
}
template<typename First, typename Second, typename... Rest>
bool does_have(int id) {
return contains<First>(id) && does_have<Second, Rest...>(id);
}
private:
std::map<std::type_index, void*> items;
};
The idea is that, after storing some items in the Collection
class, I can do something like
collection.does_have<A<int>, A<bool>, A<double>, A<float>>(15)
And if the ID 15 exists in all 4, then does_have
returns true. Otherwise, it's false.
Upvotes: 0
Views: 61
Reputation: 10591
if you have c++17
(fold expression)
template<typename ...Ts>
bool does_have(int id) {
return (contains<Ts>(id) && ...);
}
Upvotes: 2
Reputation: 20936
You can get your code to work providing only two overloads of does_have
:
template<typename T>
bool does_have(int id) {
and
template<typename First, typename... Rest>
bool does_have(int id) {
but the latter should be visible only if the size of parameters pack Rest
is greater than 0. You can do this by SFINAE:
template<typename First, typename... Rest,
std::enable_if_t<(sizeof...(Rest) > 0)>* = nullptr> // <---
bool does_have(int id) {
return contains<First>(id) && does_have<Rest...>(id);
}
Upvotes: 1