【发布时间】:2020-08-21 11:59:28
【问题描述】:
我正在使用一个模板库,因为在我的代码中,一个模板参数可以假设一个有限范围的值,我决定在建议下使用 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 我得到了以下信息:
【问题讨论】:
-
假设所有变体成员都有
rank()和dimension(int)成员返回相同的类型,这似乎是正确的。如果您收到编译错误,则意味着并非所有这些都具有类成员,或者它们返回不同的类型。 -
dimensions() 应该返回一个长度等于张量阶数 (1,2,3,...5) 的数组。我怎么解决这个问题? setRandom() 怎么样,肯定它是一个类成员,因为如果我写 'Eigen::Tensor
A({4,5})' 然后我调用 'A.setRamdom()' 它可以工作 -
这是因为,很可能每个
setRandom都会返回一个void。所有对象都有显式类型是C++的基础。auto rank=必须有一些特定的推导类型。但是,如果访问者return的类型不同,则根据变体中的值,auto rank的实际类型必须有所不同,在运行时。 C++ 不能以这种方式工作。很可能是因为auto rnk本身必须是所有可能返回类型的variant,并且由访问者直接分配,而不是返回,每个访问者返回都是无效的。 -
对于
setRandom(),在您发布的代码中您试图调用变体对象中的方法,您应该像在其他情况下一样通过访问者来执行此操作,例如std::visit([](const auto &tensor) { tensor.setRandom(); }, myTensor);。跨度>
标签: c++ templates c++17 union eigen