Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass pointer to data as argument to function expecting two-dimensional array

Tags:

c++

Consider the following code

#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); 
}

I am working with a legacy library where a lot of function arguments are like x[a][b]. However, my code relies on linear data representations (that is, I only use C++ "linear" containers, such as std::array<T, N>).

Imagine that after laborious calculations I have reached a point in the code where std::array<double, 2> contains the data that I need, and now I need to call foo on that data.

How can I "cast" (for lack of a better word) the underlying container so that I can call the legacy function which expects a double[2][2]?

I really don't want to take copies (as shown in the example) because the legacy functions such as foo are called hundreds of thousands of times.

As an extreme plus, I would like to wrap these legacy functions behind a C++ algorithm-like interface; something along the lines of:

std::vector<std::array<double, 4>> z;
fooify(z.begin(), z.end()); // calls foo(zi) for each zi in z

Edit: some answers

Thanks to @6502, I am starting with a solution along the lines of:

#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);
}

which works as expected --- of course, I can automatically deduce the "re-shaping" factor (in this case it is 2, but it will vary in the general case).

Then I will try to incorporate this "refactored" function into an algorithm.

For completeness, I add the compilation details (OS X 10.7.4 using GCC 4.8.1):

$ g++ example.cpp -std=c++11 -Wall -Wextra
$ ./a.out                                                 
1, 2
3, 4
like image 354
Escualo Avatar asked Oct 21 '22 23:10

Escualo


1 Answers

Using C-style casting

show((double (*)[2])y.data());

or using reinterpret_cast if you like to type more

show(reinterpret_cast<double (*)[2]>(y.data()));
like image 53
6502 Avatar answered Nov 03 '22 01:11

6502