【问题标题】:Applying function to a variadic template将函数应用于可变参数模板
【发布时间】:2021-04-06 04:48:34
【问题描述】:

我有一个包含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;
};

Working Example

这个想法是,在 Collection 类中存储一些项目之后,我可以做类似的事情

collection.does_have&lt;A&lt;int&gt;, A&lt;bool&gt;, A&lt;double&gt;, A&lt;float&gt;&gt;(15)

如果 ID 15 存在于所有 4 个中,则 does_have 返回 true。否则为假。

【问题讨论】:

    标签: c++ variadic-templates


    【解决方案1】:

    如果你有c++17(折叠表达式)

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

    【讨论】:

      【解决方案2】:

      只需提供两个 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);
      }
      

      Demo

      【讨论】:

      • 仅删除“中间”重载将是 IMO 的一个更简单的选择。
      • @super 你是完全正确的:),谢谢指点。
      • 你知道有什么好书或资源可以用来了解更多关于 sfinae 的信息吗?折叠表达式最终是我想要的,但我有一种感觉,概念和折叠表达式在 C++20 中并不能完全将我从 sfinae 中拯救出来。
      • 作为在线资源cppreference.com,作为一本书Templates - Complete guide - 第二版。
      猜你喜欢
      • 2021-10-01
      • 2011-11-24
      • 2014-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-01
      • 2011-11-15
      • 2011-10-19
      相关资源
      最近更新 更多