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);
我正在使用模板库,因为在我的代码中,其中一个模板参数可以采用有限范围的值,我决定根据建议使用 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);