考虑以下代码:
我正在使用一个遗留库,其中许多函数参数的格式类似于
想象一下,在艰苦的计算之后,我的代码已经到达了一个点,
如何“转换”底层容器,以便我可以调用期望一个
我真的不想拷贝(如示例中所示),因为像
作为极大的优势,我希望将这些遗留函数包装在类似于 C++ 算法界面的背后;类似于以下方式:
#include<algorithm>
#include<iostream>
#include<array>
void show(double x[2][2]) {
std::cout<<x[0][0]<<", "<<x[0][1]<<std::endl
<<x[1][0]<<", "<<x[1][1]<<std::endl;
}
int main() {
std::array<double, 4> y = {1, 2, 3, 4};
double x[2][2];
// it is safe to copy because x[2][2] consists of
// four contiguous blocks of memory in row-major order
std::copy(y.begin(), y.end(), &x[0][0]);
show(x); // this, obviously, works as expected
// but how can I cast y, or y.data(),
// or y.begin() to use the function foo?
// show(y);
}
我正在使用一个遗留库,其中许多函数参数的格式类似于
x[a][b]
。然而,我的代码依赖于线性数据表示(也就是说,我只使用C++“线性”容器,例如 std::array<T, N>
)。想象一下,在艰苦的计算之后,我的代码已经到达了一个点,
std::array<double, 2>
包含了我需要的数据,现在我需要在该数据上调用 foo
。如何“转换”底层容器,以便我可以调用期望一个
double[2][2]
的遗留函数?我真的不想拷贝(如示例中所示),因为像
foo
这样的遗留函数会被调用数十万次。作为极大的优势,我希望将这些遗留函数包装在类似于 C++ 算法界面的背后;类似于以下方式:
std::vector<std::array<double, 4>> z;
fooify(z.begin(), z.end()); // calls foo(zi) for each zi in z
编辑:一些答案
感谢 @6502,我开始采用以下解决方案:
#include<algorithm>
#include<iostream>
#include<array>
namespace legacy {
void show(double x[2][2]) {
std::cout<<x[0][0]<<", "<<x[0][1]<<std::endl
<<x[1][0]<<", "<<x[1][1]<<std::endl;
}
}
template<size_t N, typename Container>
void show(Container& y) {
return legacy::show(reinterpret_cast<double(*)[N]>(y.data()));
}
int main() {
std::array<double, 4> y = {1, 2, 3, 4};
show<2>(y);
}
这个函数的功能与预期相符 - 当然,我可以自动推导出“重新塑形”的因素(在本例中为2,但在一般情况下会有所变化)。
接下来,我将尝试将这个“重构”函数纳入算法中。
为了完整起见,我附加编译细节(使用GCC 4.8.1的OS X 10.7.4):
$ g++ example.cpp -std=c++11 -Wall -Wextra
$ ./a.out
1, 2
3, 4
f(T a[2][2])
实际上是f(T (* a)[2])
- 你应该使用函数签名来明确表示这一点,而不是完全误导性的语法a[2][2]
(实际上应该被弃用,因为它对程序员来说是在撒谎)。这表明这些类型实际上是不兼容的。 - Konrad Rudolphshow
函数期望一个包含两个指针的数组,而 OP 正试图传递一个包含四个double
的数组。 - Konrad Rudolphshow()
函数期望一个指针,而不是两个指针的数组。这是一个真正的 2D 数组。OP 更改了std::array<>
的声明以解决从2
到4
的空间差异问题,因此回答了我的问题,很可能只是他的笔误。 - WhozCraig