代码之家  ›  专栏  ›  技术社区  ›  Afshin

是否可以在没有类型信息的情况下转换为模板化类?

c++
  •  0
  • Afshin  · 技术社区  · 2 年前

    让我们假设我有一个模板化的类,如下所示:

    template<typename Fn>
    struct S {
      S(Fn fn) : fn_(fn) {}
    
      const auto& fn() const {
        return fn_;
      }
      Fn fn_;
    }
    

    有时您需要将对象作为 void* ,所以如果我有一个这样的指针:

    void* ptr = new S{[]() { std::cout << "hi!\n";}};
    

    一切都很好。但问题是,如果我试着投 ptr 回到我的班级以访问 fn() 方法,我将需要类型信息。因此以下代码将 编译:

    auto s = static_cast<S*>(ptr);
    

    现在我的问题是,是否有一种模式或方法将类型信息与数据一起携带,以使这种转换成为可能?使用任何返回正确实例的方法/模式都可以。这个问题的用例是当您使用在方法之间传递上下文的库时 无效* 。如果要使用模板化类作为该上下文,则会出现此问题。

    知道吗?

    2 回复  |  直到 2 年前
        1
  •  2
  •   yuri kilochek    2 年前

    这里的核心问题是,您希望使用lambda作为类型的模板参数,然后希望能够将其强制转换为 void* 。lambda的类型未知,由编译器生成。即使它是已知的,你也无法键入它。

    因此,您需要从中删除类型 S 然后把它塞进 S 的构造函数:

    struct S {
      template<typename Func>
      S(Func &&fn) : fn_(std::forward<Func>(fn)) {}
    
      auto const& fn() const {
        return fn_;
      }
    
      std::function<void()> fn_;
    }
    

    您需要在内部擦除该类型,以便尝试撤消擦除的代码可以使用已知类型。

        2
  •  0
  •   Henrique Bucher    2 年前

    我可以看到几个选项:

    1. 从基类继承每个类并使用动态多态性。

    2. 使用std::函数

    3. 使用std::变体

    4. 使用std::any

    这些方法中的每一种在成本和功能上都有所不同,但都可以随心所欲。