std::variant 和 std::visit 的联合模板

Union Template with std::variant and std::visit

我正在使用模板库,因为在我的代码中,其中一个模板参数可以采用有限范围的值,我决定根据建议使用 std::variant 并在其中声明所有对象我可能需要:

std::variant<TemplateClass<1>, TemplateClass<2>, ..., TemplateClass<5>>

我从未使用过此实用程序。

要访问 TemplateClass 的方法,我必须使用 std::visit,但有时它可以工作,而其他的则不能,比如 no member function XXX in std::variant < .... > 或“在函数模板特化的实例化中......” [我什至不明白这里有什么问题]

具体来说,我正在使用 Eigen::Tensor 库,当我调用 rank()dimension(n) 等方法时,它会起作用,而 dimensions()setRandom() 没有。

下面是我的实施草案

std::variant<Eigen::Tensor<double, 1>, Eigen::Tensor<double, 2>, /* ... */> makeTensor(
    int i, const std::initializer_list<int> dims) {
  switch (i) {
    case 1: {
      Eigen::Tensor<double, 1> T1;
      T1.resize(dims);
      return T1;
    }

    case 2: {
      Eigen::Tensor<double, 2> T2;
      T2.resize(dims);
      return T2;
    }

      /* ... */
  }
}

int main() {
  auto myTensor{makeTensor(2, {4, 5})};  // Tensor 2D 4x5

  // Working methods
  auto rnk = std::visit([](const auto &tensor) { return tensor.rank(); }, myTensor);

  auto dim1 = std::visit([](const auto &tensor) { return tensor.dimension(0); }, myTensor);

  // Not working methods

  auto dimsTens =
      std::visit([](const auto &tensor) { return tensor.dimensions(); }, myTensor);  // 5 times same error saying
  //'In instantiation of function template specialization 'std::visit<(lambda at
  /// home/virginie/Desktop/Project/main.cpp:62:33),
  // std::variant<Eigen::Tensor<double, 1, 0, long>, Eigen::Tensor<double, 2, 0, long>, Eigen::Tensor<double, 3, 0,
  // long>, Eigen::Tensor<double, 4, 0, long>, Eigen::Tensor<double, 5, 0, long>> &>''

  std::visit([&myTensor]() { myTensor.setRandom(); });  // 'No member setRandom() in std::variant<...>'
}

我是不是用错了std::visit

---- 编辑 ----

在@florestan 的建议下,我已经解决了 dimensions() 相关的问题,而 setRandom 我得到了以下信息:

在 /..../ 包含的文件中 main.cpp 从这里需要

您需要return 为所有可能的备选方案选择相同的类型。在dimension的情况下,您需要将数组元素复制到一个向量中,例如

这样的事情应该有所帮助:

 auto dimsTens=std::visit(
    [](const auto &tensor) {
       auto dims = tensor.dimensions();
       return std::vector<int>(dims.begin(), dims.end());
    }, myTensor);

第二个错误是因为你没有以正确的方式调用std::visit。它需要两个参数,第一个是函数,第二个是要访问的变体。以下应该有效。

std::visit([](auto& t){ t.setRandom();}, myTensor); 

实时代码: https://godbolt.org/z/vq4PYo