我正在使用一个模板库,由于在我的代码中一个模板参数可以取有限范围内的值,所以在建议下决定使用std::variant,并在其中声明我可能需要的所有对象:
std::variant<TemplateClass<1>, TemplateClass<2>, ..., TemplateClass<5>>
我从未使用过这个实用程序。
要访问TemplateClass的方法,我必须使用`std::visit`,但有时它有效,有时又不起作用,会报告`std::variant <....>中没有成员函数XXX`或`“函数模板特化的实例化…”`(我甚至不知道问题出在哪里)。
具体来说,我正在使用`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)
成员,这似乎是正确的。如果您遇到编译错误,则意味着其中某些成员没有该类成员,或者它们返回不同的类型。 - Sam VarshavchiksetRandom
都会返回一个void
。在 C++ 中,所有对象都必须具有显式类型,因此auto rank=
必须具有某些特定的推断类型。但是,如果访问者根据变量中的值返回不同的类型,则auto rank
的实际类型必须在运行时变化。C++ 不是这样工作的。很可能是因为auto rnk
本身必须是所有可能返回类型的variant
,并由访问者直接分配,而不是每个访问者都返回void
。 - Sam Varshavchikdimensions()
函数:https://gitlab.com/libeigen/eigen/-/blob/3.3.7/unsupported/Eigen/CXX11/src/Tensor/Tensor.h#L102,以及这里的setRandom()
函数:https://gitlab.com/libeigen/eigen/-/blob/3.3.7/unsupported/Eigen/CXX11/src/Tensor/TensorBase.h#L849-856。建议使用返回类型DSizes
,它有一个用于秩的模板参数。您可以将其封装为Array<IndexType, Dynamic, 1>
(例如ArrayXi
)。 - jdehesasetRandom()
,在您发布的代码中,您正在尝试在变量对象中调用该方法,您应该像其他情况一样通过访问者来完成,例如std::visit([](const auto &tensor) { tensor.setRandom(); }, myTensor);
。 - jdehesa