简体   繁体   English

将 function 应用于可变参数模板

[英]Applying function to a variadic template

I have a class that holds a map of Collection<T> , which is cast into a void* for storage purposes.我有一个 class ,它包含一个 map 的Collection<T> ,它被转换成一个void*用于存储目的。

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> .每个Collection<T>可以保存一个 ID 数组,我想提供一些可变参数模板魔术来判断某个 ID 是否存在于Collection<T>的某个分组中。 I'm just not sure how to go about it, after looking over some examples there is something that I am missing.我只是不确定如何 go 关于它,在查看了一些示例之后,我缺少一些东西。

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;
};

Working Example工作示例

The idea is that, after storing some items in the Collection class, I can do something like这个想法是,在Collection class 中存储一些项目后,我可以做类似的事情

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.如果 ID 15 存在于所有 4 个中,则does_have返回 true。 Otherwise, it's false.否则就是假的。

if you have c++17 (fold expression)如果你有c++17 (折叠表达式)

template<typename ...Ts>
bool does_have(int id) {
   return (contains<Ts>(id) && ...);
}

You can get your code to work providing only two overloads of does_have :你可以让你的代码工作只提供两个重载的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:但后者只有在参数包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);
}

Demo演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM