【问题标题】:How to use a compile-time interface with a runtime type?如何使用具有运行时类型的编译时接口?
【发布时间】:2021-01-15 13:04:34
【问题描述】:

我有一个函数,它接受 T 并在提供的对象上调用特定函数。到目前为止,它是在编译时对象中使用的,所以一切都很好。最小的例子:

#include <iostream>

struct A {
   void fun() const { std::cout << "A" << std::endl; }
};

struct B {
   void fun() const { std::cout << "B" << std::endl; }
};

template<class T>
void use_function(const T& param) {
   param.fun();
}

int main() {
   use_function(A{}); // "A"
   use_function(B{}); // "B"
   return 0;
}

现在我正在尝试将 use_function() 与在运行时创建的对象一起使用并且遇到困难。我不能使用std::variantstd::any,因为我需要将类型作为模板参数提供给它们的访问函数——尽管它们的变体all 都实现了函数接口。 (失败的)变体方法的示例:

using var_type = std::variant<A, B>;

struct IdentityVisitor {
   template<class T>
   auto operator()(const T& alternative) const -> T {
      return alternative;
   }
};

int main() {
   var_type var = A{};

   // error C2338: visit() requires the result of all potential invocations to have the same type and value category (N4828 [variant.visit]/2).
   use_function(std::visit(IdentityVisitor{}, var));
   return 0;
}

可能的是直接调用具有适当类型的函数,如下所示:

if (rand() % 2 == 0)
   use_function(A{});
else
   use_function(B{});

仅将其存储在两者之间是我无法工作的。

我在技术层面上理解,但在想出一个优雅的解决方案时遇到了麻烦。有吗?我知道即使是轻量级继承,我也可以重写对象——但我试图看看完全避免它是否可行,即使只是作为一种练习来避免 OOP 以支持模板和概念。我感觉应该使用变体,但显然不是。

【问题讨论】:

  • 旁白:std::visit&lt;var_type&gt;(IdentityVisitor{}, var) 是有效的,但让你无处可去
  • 你确定? 'std::visit': no matching overloaded function found
  • 糟糕,没注意到那是从 C++20 开始的

标签: c++ templates variant


【解决方案1】:
std::visit([](auto const& x) { use_function(x); }, var);

【讨论】:

    【解决方案2】:

    如果重载集是对象,您可以将use_function 直接传递给std::visit。因为它们不是,所以您需要将其包装在将被实例化为对正确重载的调用的东西中。

    std::visit([](auto const& x) { use_function(x); }, var);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-25
      • 2013-01-04
      • 2016-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多