将函数应用于可变参数模板
Applying function to a variadic template
我有一个 class,其中包含 Collection<T>
的地图,为了存储目的,它被转换成 void*
。
每个 Collection<T>
都可以包含一个 ID 数组,我想提供一些可变参数模板魔术,以便能够判断 Collection<T>
的某些分组中是否存在某些 ID。我只是不确定该怎么做,在查看了一些示例后,我缺少了一些东西。
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;
};
我的想法是,在 Collection
class 中存储一些项目后,我可以做类似
的事情
collection.does_have<A<int>, A<bool>, A<double>, A<float>>(15)
如果 ID 15 在所有 4 个中都存在,则 does_have
returns 为真。否则为假。
您只需重载 does_have
:
的两个就可以让您的代码正常工作
template<typename T>
bool does_have(int id) {
和
template<typename First, typename... Rest>
bool does_have(int id) {
但后者只有在参数包 Rest
的大小大于 0 时才应该可见。您可以通过 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);
}
如果你有c++17
(折叠表达式)
template<typename ...Ts>
bool does_have(int id) {
return (contains<Ts>(id) && ...);
}
我有一个 class,其中包含 Collection<T>
的地图,为了存储目的,它被转换成 void*
。
每个 Collection<T>
都可以包含一个 ID 数组,我想提供一些可变参数模板魔术,以便能够判断 Collection<T>
的某些分组中是否存在某些 ID。我只是不确定该怎么做,在查看了一些示例后,我缺少了一些东西。
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;
};
我的想法是,在 Collection
class 中存储一些项目后,我可以做类似
collection.does_have<A<int>, A<bool>, A<double>, A<float>>(15)
如果 ID 15 在所有 4 个中都存在,则 does_have
returns 为真。否则为假。
您只需重载 does_have
:
template<typename T>
bool does_have(int id) {
和
template<typename First, typename... Rest>
bool does_have(int id) {
但后者只有在参数包 Rest
的大小大于 0 时才应该可见。您可以通过 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);
}
如果你有c++17
(折叠表达式)
template<typename ...Ts>
bool does_have(int id) {
return (contains<Ts>(id) && ...);
}