如何处理使用不同类型索引(size_t、int、...)的不同库(例如 stl 和 eigen3)的混合
How to handle mixing of different libraries (eg. stl and eigen3) that use different types for indices (size_t, int, ...)
我有以下问题。我有一些使用 Eigen3 的代码。 Eigen3 使用 int 或 long int 作为索引。在代码中的某些点,我必须将特征数组中的值存储在 std::vector
.
中
这里是一些例子:
std::vector myStdVector;
Eigen::VectorXd myEigen;
....
for(size_t i=0; i<myStdVector.size(); i++)
{
myStdVector[i] = myEigen(i);
}
这里我得到了编译器警告:
warning: implicit conversion loses integer precision: 'const size_t'
(aka 'const unsigned long') to 'int'
所以我当然可以在所有出现这种情况的函数中加一个static_cast<int>(i)
,但我想知道是否有更好的方法来处理这种情况。我想这也发生在许多其他 "library-mixing" 身上。
在这种情况下,我建议使用较小容器的索引类型;这将是 Eigen 的索引类型,由您的 Eigen::VectorXd
确定。理想情况下,它将用作 Eigen::Index
,以实现向前兼容性。
可能还值得研究一下 Eigen 如何定义其索引类型。特别是 you are allowed to redefine it if necessary, by changing a preprocessor directive,通过 #define
符号 EIGEN_DEFAULT_DENSE_INDEX_TYPE
;它默认为 std::ptrdiff_t
.
[但是请注意,在我自己的代码中,我通常更喜欢使用较大的索引(在本例中,size_t
),但是像使用较小的索引一样进行范围检查索引类型(如果适用)(在本例中,Eigen::Index
)。然而,这只是个人喜好,不一定是我认为的最佳选择。]
一般来说,在尝试选择最佳索引类型时,我建议您查看它们的可用范围。首先,如果一个或多个潜在类型是有符号的,并且如果一个或多个有符号潜在类型允许负值*,您需要消除任何无符号类型,尤其是那些大于最大的有符号类型。然后,您将查看您的用例,消除任何不适合您预期目的的类型,并从剩余的潜在类型中选择最适合的类型。
在您的具体情况下,您希望将来自 Eigen3 容器的值存储在 STL 容器中,其中 Eigen3 容器使用 ptrdiff_t
进行索引并且(如您的评论中所述)据您所知仅使用非-负指标值。在这种情况下,两者都是可行的选择; ptrdiff_t
提供的非负索引值范围很好地适合 size_t
的范围,循环条件将由你的 VectorXd
决定(因此也保证适合Eigen3 容器的索引类型)。因此,这两种潜在类型都是可行的选择。由于目前不需要 size_t
提供的额外范围,我认为您的 Eigen 设置提供的索引类型稍微更适合手头的任务。
*:虽然由于索引的工作方式,假设索引值始终为正通常是安全的,但我可以看到一些允许负值的情况。不过,这些通常很少见。
请注意,我假设您的示例代码中的循环条件 i<myStdVector.size()
是错字,因为它与初始描述或循环体内执行的操作不一致。如果我错了,那么这个决定就会变得更加复杂。
我有以下问题。我有一些使用 Eigen3 的代码。 Eigen3 使用 int 或 long int 作为索引。在代码中的某些点,我必须将特征数组中的值存储在 std::vector
.
这里是一些例子:
std::vector myStdVector;
Eigen::VectorXd myEigen;
....
for(size_t i=0; i<myStdVector.size(); i++)
{
myStdVector[i] = myEigen(i);
}
这里我得到了编译器警告:
warning: implicit conversion loses integer precision: 'const size_t' (aka 'const unsigned long') to 'int'
所以我当然可以在所有出现这种情况的函数中加一个static_cast<int>(i)
,但我想知道是否有更好的方法来处理这种情况。我想这也发生在许多其他 "library-mixing" 身上。
在这种情况下,我建议使用较小容器的索引类型;这将是 Eigen 的索引类型,由您的 Eigen::VectorXd
确定。理想情况下,它将用作 Eigen::Index
,以实现向前兼容性。
可能还值得研究一下 Eigen 如何定义其索引类型。特别是 you are allowed to redefine it if necessary, by changing a preprocessor directive,通过 #define
符号 EIGEN_DEFAULT_DENSE_INDEX_TYPE
;它默认为 std::ptrdiff_t
.
[但是请注意,在我自己的代码中,我通常更喜欢使用较大的索引(在本例中,size_t
),但是像使用较小的索引一样进行范围检查索引类型(如果适用)(在本例中,Eigen::Index
)。然而,这只是个人喜好,不一定是我认为的最佳选择。]
一般来说,在尝试选择最佳索引类型时,我建议您查看它们的可用范围。首先,如果一个或多个潜在类型是有符号的,并且如果一个或多个有符号潜在类型允许负值*,您需要消除任何无符号类型,尤其是那些大于最大的有符号类型。然后,您将查看您的用例,消除任何不适合您预期目的的类型,并从剩余的潜在类型中选择最适合的类型。
在您的具体情况下,您希望将来自 Eigen3 容器的值存储在 STL 容器中,其中 Eigen3 容器使用 ptrdiff_t
进行索引并且(如您的评论中所述)据您所知仅使用非-负指标值。在这种情况下,两者都是可行的选择; ptrdiff_t
提供的非负索引值范围很好地适合 size_t
的范围,循环条件将由你的 VectorXd
决定(因此也保证适合Eigen3 容器的索引类型)。因此,这两种潜在类型都是可行的选择。由于目前不需要 size_t
提供的额外范围,我认为您的 Eigen 设置提供的索引类型稍微更适合手头的任务。
*:虽然由于索引的工作方式,假设索引值始终为正通常是安全的,但我可以看到一些允许负值的情况。不过,这些通常很少见。
请注意,我假设您的示例代码中的循环条件 i<myStdVector.size()
是错字,因为它与初始描述或循环体内执行的操作不一致。如果我错了,那么这个决定就会变得更加复杂。