C++ eigen pointer to a Eigen::Map<Eigen::VectorXd> object - c++

Is it possible to define a pointer to a Eigen::Map object? The original code is quite complex but here is what I am trying to achieve (pseudo code)
void testfunction1(... XPtr){
// XPtr is a pointer
// create a vector, map it to a Map object and make XPtr point to the latter
VectorXd Xnew(9);
Xnew << 10, 20, 30, 40, 50, 60, 70, 80, 90;
Map<VectorXd> XnewMap(Xnew.data(), 9);
// make XPtr point to XnewMap so that Xnew data can be
// accessed outside testfunction1()
// ... how? I suspect this to involve some dynamic memory allocation
};
void testfunction2(bool yes){
// main function
VectorXd XR(9);
XR << 1, 2, 3, 4, 5, 6, 7, 8, 9;
const Map<VectorXd> X(XR.data(), 9); // yes the mapped version is needed
// create a pointer to X, say XPtr
// ... how?
if(yes){ // make XPtr point to XnewMap which is defined in testfunction1()
testfunction1(XPtr);
};
//... some computations
// make XPtr point again to X
// ... how?
};

First of all no need to use pointers here because Map is already essentially a pointer, so it would be simpler so update the Map object with placement new. Nonetheless, your current design would require allocation within testfunction1 and deallocation within testfunction2 in case it has been allocated, which is not really safe. So better adopt a functional design by putting "some computations" within a function (or a named lambda), make testfunction1 return by value:
VectorXd testFunction1() { return Xnew; }
void testfunction2(bool yes){
VectorXd XR(9);
XR << 1, 2, 3, 4, 5, 6, 7, 8, 9;
const Map<VectorXd> X(XR.data(), 9);
auto func = [&] (Eigen::Ref<VectorXd> X) {
/* some computation */
}
if(yes) func(testfunction1());
else func(X);
};
If you really want to keep your current logic, then here is a self-contained example using placement new:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
void testfunction1(Map<VectorXd> &XMap){
double * Xnew = new double[9];
::new (&XMap) Map<VectorXd>(Xnew,9);
XMap << 10, 20, 30, 40, 50, 60, 70, 80, 90;
};
int main()
{
bool yes = true;
VectorXd XR(9);
XR << 1, 2, 3, 4, 5, 6, 7, 8, 9;
Map<VectorXd> X(XR.data(), 9);
if(yes) testfunction1(X);
// use X ...
cout << X.transpose() << endl;
// restore X and free memory allocated in testfunction1
if(yes){
delete[] X.data();
::new (&X) Map<VectorXd>(XR.data(),9);
}
cout << X.transpose() << endl;
}
which is pretty bad because it can leak if an exception is raised when using X. You could workaround manual memory management by asking testFunction1 to return a VectorXd (or anything that handle memory allocation/deallocation on its own) and do the placement new in the main function:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
VectorXd testfunction1(){
VectorXd Xnew(9);
Xnew << 10, 20, 30, 40, 50, 60, 70, 80, 90;
return Xnew;
};
int main()
{
bool yes = true;
VectorXd XR(9);
XR << 1, 2, 3, 4, 5, 6, 7, 8, 9;
Map<VectorXd> X(XR.data(), 9);
{
VectorXd X2;
if(yes) {
X2 = testfunction1(); // shallow copy thanks to move semantic
::new (&X) Map<VectorXd>(X2.data(),9);
}
// use X ...
cout << X.transpose() << endl;
// restore X
::new (&X) Map<VectorXd>(XR.data(),9);
}
cout << X.transpose() << endl;
}
Finally, if the content of X should be read-only, then use Map<const VectorXd> and not const Map<VectorXd> as in your initial question.

Related

how to print an n-dimensional array in c++

I would like to write a function that can print different arrays. For instance:
#include<iostream>
using namespace std;
int main(){
int a[10];
int b[3][2];
for(int i = 0; i < 10; i++){
a[i] = i;
}
for(int i = 0; i < 3; i++){
for(int j = 0; j < 2; j++){
b[i][j] = i * 2 + j;
}
}
print_arr(a, /*some input*/);
// output: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
print_arr(b, /*some input*/);
// output:
// 0, 1
// 2, 3
// 4, 5
return 0;
}
can somebody help me or say that this is impossible.
maybe this question is already answered. In that case please can you share the link of that question
You could create a function template that unwraps the array recursively.
Example:
#include <iostream>
#include <type_traits>
// only enable the function for arrays
template<class T, std::enable_if_t<std::is_array_v<T>, int> = 0>
void print_arr(const T& x) {
for(auto& in : x) {
if constexpr (std::rank_v<T> > 1) // more dimensions to go
print_arr(in); // call to unwrap next dimension
else
std::cout << in << ' '; // last dimension, print the value
}
std::cout << '\n';
}
Demo
Since the name print_arr suggests that you will not need SFINAE you could also replace the enable_if_t part of the template with a static_assert inside the function:
template<class T>
void print_arr(const T& x) {
static_assert(std::is_array_v<T>);
// ...
Instead of streaming directly to std::cout, you could add a std::ostream& parameter to make it stream to any stream
template<class T>
void print_arr(std::ostream& os, const T& x) {
static_assert(std::is_array_v<T>);
for(auto& in : x) {
if constexpr (std::rank_v<T> > 1)
print_arr(os, in);
else
os << in << ' ';
}
os << '\n';
}
// ...
print_arr(std::cout, a);
print_arr(std::cout, b);
Or you could make it return a std::string of the complete output which lets you do what you want with it afterwards.
Example:
#include <sstream>
template<class T>
std::string print_arr(const T& x) {
static_assert(std::is_array_v<T>);
std::ostringstream os;
for(auto& in : x) {
if constexpr (std::rank_v<T> > 1)
os << print_arr(in);
else
os << in << ' ';
}
os << '\n';
return os.str();
}
// ...
std::cout << print_arr(a);
std::cout << print_arr(b);
Ted Lyngmo's answer is definitely the most concise, and probably the closest to achieving what you asked for, but there's still a few things worth pointing out including an alternate solution that might make sense in some circumstances.
First of all, it's important for anyone reading this to understand that C and C++ types don't include any kind of runtime type information by default. Yes it's true, RTTI exists for record types, but a built-in C array like int arr[2][3] is not much more than a bit of sugar to say "give me a region of memory large enough to store 6 ints". This is in contrast for example to a language like python, where a list object will include metadata about the size and contents. It's this metadata that allows you to write very flexible functions than can query the object itself about its structure, and of course it comes at a cost.
When we introduce a templated solution like the one above, we haven't added runtime type information, we've asked the compiler to generate code for every possible permutation of array type that we might need. This is fine if you only have a couple of them, but if the function gets used a lot, with many different array types, things grow really fast. This could actually become a problem in some environments. Consider for example the following main function:
int main(int argc, char **argv)
{
int arr1[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
print_arr(arr1);
int arr2[3] = {13, 14, 15};
print_arr(arr2);
int arr3[3][2][2] = {{{10, 20}, {30, 40}}, {{50, 60}, {70, 80}}, {{90, 100}, {110, 120}}};
print_arr(arr3);
return 0;
}
And now look at the AST that gets generated:
jon#prompt$ clang++ -fsyntax-only -Xclang -ast-dump test.cpp -std=c++17 | grep FunctionDecl | grep print_arr
| |-FunctionDecl 0x10921fd88 <line:6:1, line:15:1> line:6:6 print_arr 'void (const T &)'
| |-FunctionDecl 0x109224c18 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[3][4])'
| |-FunctionDecl 0x109225ab8 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[3])'
| |-FunctionDecl 0x1092270a8 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[3][2][2])'
| |-FunctionDecl 0x10933db08 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[4])'
| |-FunctionDecl 0x1093539a8 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[2][2])'
| `-FunctionDecl 0x1093552d8 <line:6:1, line:15:1> line:6:6 used print_arr 'void (int const &[2])'
Here you see the compiler has emitted a different version of the print_arr function for every permutation of array size we've used. This isn't exactly what you could reasonably call "one function", it's actually many functions that have each been automatically generated by the compiler. It's a tiny amount of text to write in a cpp file, but the actual amount of code that gets generated is significant.
An alternate way to solve this problem is to just include type information in the print_arr function. Here's an example of an implementation that is WYSIWYG, and will let you do the same thing though you need to provide the type metadata manually:
const int *print_arr(const int *arr, const int rank, const int *lengths)
{
const char *p_sep = "";
printf("{");
if (rank > 1) {
for (int i = 0; i < lengths[0]; i++) {
printf("%s", p_sep);
arr = print_arr(arr, rank - 1, &lengths[1]);
p_sep = ", ";
}
} else {
for (int i = 0; i < lengths[0]; i++) {
printf("%s%d", p_sep, *arr++);
p_sep = ", ";
}
}
printf("}");
return arr;
}
And here's how you would use it with the same example arrays:
int main(int argc, char **argv)
{
int arr1[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
print_arr(&arr1[0][0], 2, (int[2]){3, 4});
printf("\n");
int arr2[3] = {13, 14, 15};
print_arr(&arr2[0], 1, (int[1]){3});
printf("\n");
int arr3[3][2][2] = {{{10, 20}, {30, 40}}, {{50, 60}, {70, 80}}, {{90, 100}, {110, 120}}};
print_arr(&arr3[0][0][0], 3, (int[3]){3, 2, 2});
printf("\n");
return 0;
}
Output:
jon#promptC$ ./test
{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}
{13, 14, 15}
{{{10, 20}, {30, 40}}, {{50, 60}, {70, 80}}, {{90, 100}, {110, 120}}}
This approach has a few advantages, the most important being that the compiler emits pretty much exactly what's written. It also forces you to be very explicit in the code, which is probably good in this case.
As always with C and C++ you need to know what's most appropriate for the situation you find yourself in.

How to return a struct which contains an array pointer from a function?

I have this struct and declaration in .h file,
struct strct
{
int *arry;
};
strct func01();
and this function in .cpp file,
strct func01()
{
int temp_arry[] = {5, 6, 7, 8, 9};
strct rtrn;
rtrn.arry = temp_arry;
return rtrn;
}
and i call the function like,
strct test = func01();
printf("%d", test.arry);
It prints some random numbers. I want to print the full array.
Before we start, let's recall the behavior of the sizeof operator:
Case of : int *
int *arry;
int iSize = sizeof (arry); <-- Return size of pointer and NOT number of elements
Case of : int []
int temp_arry[] = {5, 6, 7, 8, 9};
int iSize = sizeof (temp_arry); <-- Return total memory size allocated for 5 elements
You understand now that the composition of your structure does not allow you to determine the number of elements of your int *arry struct member. Therefore, you don't know how many element you should display.
If you wish to keep your program without using the STL: vector, array, ... you must complete your structure as follows:
struct strct
{
int size; // Contains the number of elements to use
int *arry;
};
strct func01();
strct func01()
{
strct rtrn;
int tab_size = 5;
// it is a temp variable. Destroyed when function ends.You can not use it !
int temp_arry[] = {5, 6, 7, 8, 9};
// This table is allocated with new and can be used
int *permanent_arry = new int [tab_size];
for (int i=0; i<tab_size; i++)
permanent_arry[i] = i;
rtrn.arry = permanent_arry;
rtrn.size = tab_size;
return rtrn;
}
int main ()
{
strct test = func01();
for (int i=0; i<test.size; i++)
printf("%d ", test.arry[i]);
// dont forget to delete memory
delete [] test.arry;
}
First, this code is wrong because:
the lifetime of temp_arry[] is end after func01 returns.
you are printing a pointer, not an array.
Second, if you want to print the full array, you'd better redesign your code, for example, you may use vector to clean up your code. (this code needs C++ 11)
struct strct
{
std::vector<int> arry;
};
strct func01();
strct func01()
{
std::vector<int> temp_arry = {5, 6, 7, 8, 9};
strct rtrn;
rtrn.arry = temp_arry;
return rtrn;
}
strct test = func01();
for(auto i : test)
std::cout << i << " ";
Note: most of the time there's no point to use built-in arrays as return value, even though it will decay to a pointer prvalue.

How to fill array of struct containing pointer arrays

I have an small and quite simple issue in C++. I want to fill array of struct containing double arrays. How can I do that?
typedef struct
{
double *inputs[2];
double *target[1];
} Data;
Data data[]
{
new double[2]{10, 20}, new double[1]{30},
new double[2]{40, 50}, new double[1]{60},
new double[2]{70, 80}, new double[1]{90},
new double[2]{100, 110}, new double[1]{120}
};
and in the main()
printf("data[0]: inputs: %f %f, targets: %f\n",
*data[0].inputs[0],
*data[0].inputs[1],
*data[0].target[0]);
This is my idea, but when I run that it will print this:
data[0]: inputs: 10.000000 30.000000, targets: 40.000000
Of course, at the end of the array data (like 3rd or 4th item) it will cause UNAUTHORIZED ACCESS TO MEMORY
Thank you for your ideas and patience ;)
Using modern c++ makes your code both simpler and safer:
#include <iostream>
#include <array>
#include <vector>
struct Data {
std::array<double,2> inputs;
std::array<double,1> target;
};
int main()
{
std::vector<Data> data = {
{ {10, 20}, {30} },
{ {40, 50}, {60} },
{ {70, 80}, {90} },
{ {100, 110}, {120} }
};
std::cout << "data[0]: inputs: " << data[0].inputs[0] << " " << data[0].inputs[1] << ", targets: " << data[0].target[0] << "\n";
}
Your original problem is that double *inputs[2] declares a 2 element array of pointers to double not a pointer to a 2 element array of doubles.
Your Data struct contains 2 fields, array of 2 double pointers, and array of 1 double pointers.
That means that initalizing it takes up to 3 double pointers, which means that in your initalization really looks like this
Data data[]{
{new double[2]{ 10, 20 }, new double[1]{ 30 }, new double[2]{ 40, 50 }}, //1st object
{new double[1]{ 60 }, new double[2]{ 70, 80 }, new double[1]{ 90 }}, //2nd object
{new double[2]{ 100, 110 }, new double[1]{ 120 }} //3rd object but 2 parameters??
};
When trying to print it in a loop, 3rd object will cause a segfault, as target field hasn't been properly initalized (when debugging with Visual Studio it's set to null, not sure about other compilers).
Your problem is here:
typedef struct {
double *inputs[2]; // this
double *target[1]; // this
} Data;
This is an array of pointers and hopefully assumed to behave live a dynamic 1D array.
Simple fix is:
struct Data {
double *inputs = nullptr;
double *target = nullptr;
} ;
However, you have a lot of heap memory allocation using new, which makes a tedious task to delete and thereby the management of your data structure really difficult.
I would strongly suggest you to use std::vector<>, which makes your task much easier and more cleaner.
#include <vector>
#include <iostream>
struct Data
{
std::vector<double> inputs; // use instead of double *inputs[2];
std::vector<double> target; // use instead of double *target[1];
//Data(const std::vector<double>& a, const std::vector<double>& b) :inputs(a), target(b){}
};
int main()
{
std::vector<Data> data = // now in your main structure array
{ { {10, 20}, {30} },
{ {40, 50}, {60} },
{ {70, 80}, {90} },
{ {100, 110},{120} }
};
// access using range based loop now
for(const Data& each_strcut: data)
std::cout << each_strcut.inputs[0] << " " << each_strcut.inputs[1]
<<"\t" << each_strcut.target[0] << std::endl;
return 0;
}

Cannot convert vector<int> to int* for bool testPIN

For a class assignment I had to rewrite this code using vectors instead of arrays. I figured I would use the existing arrays and assign them as a vector. But I get:
error: cannot convert 'std::vector' to 'int*' for argument '1' to
'bool testPIN(int*, int*, int)'
How can I get around this error?
#include <iostream>
#include<vector>
using namespace std;
// Function Prototype
bool testPIN(int [], int [], int);
int main ()
{
const int NUM_DIGITS = 7; // Number of digits in a PIN
int cpin1[NUM_DIGITS] = {2, 4, 1, 8, 7, 9, 0}; // Base set of values.
int cpin2[NUM_DIGITS] = {2, 4, 6, 8, 7, 9, 0};
int cpin3[NUM_DIGITS] = {1, 2, 3, 4, 5, 6, 7};
vector<int> pin1(cpin1, cpin1+7) ;
vector<int> pin2(cpin2, cpin2+7) ;
vector<int> pin3(cpin3, cpin3+7) ;
if (testPIN(pin1, pin2, NUM_DIGITS))
cout << "ERROR: pin1 and pin2 report to be the same.\n";
else
cout << "SUCCESS: pin1 and pin2 are different.\n";
if (testPIN(pin1, pin3, NUM_DIGITS))
cout << "ERROR: pin1 and pin3 report to be the same.\n";
else
cout << "SUCCESS: pin1 and pin3 are different.\n";
if (testPIN(pin1, pin1, NUM_DIGITS))
cout << "SUCCESS: pin1 and pin1 report to be the same.\n";
else
cout << "ERROR: pin1 and pin1 report to be different.\n";
return 0;
}
bool testPIN(int custPIN[], int databasePIN[], int size)
{................}
In these situations, it helps to read a good reference. You would need to get the vector's underlying data array:
testPIN(pin1.data(), pin2.data(), NUM_DIGITS))
If your implementation does not support C++11, you can do the following:
testPIN(&pin1[0], &pin2[0], NUM_DIGITS))
But if you have been asked to re-implement some code to use vectors, you may want to re-implement the testPIN function instead:
bool testPIN(const std::vector<int>& custPIN1,
const std::vector<int>& custPIN2);
and then just pass the vectors:
testPIN(pin1, pin2);
testPIN(&pin1[0], &pin2[0], NUM_DIGITS)
because the vector's internal memory structure is same with array.
Please check this.
How to convert vector to array in C++

Returning a pointer to an array C++

I have a function that needs to return a pointer to an array:
int * count()
{
static int myInt[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
return &myInt[10];
}
inside my main function I want to display one of the ints from that array, like here at index 3
int main(int argc, const char * argv[])
{
int myInt2[10] = *count();
std::cout << myInt2[3] << "\n\n";
return 0;
}
this however gives me the error: "Array initializer must be an initializer list"
how do I create an array within my main function that uses the pointer to get the same elements as the array at the pointer?
A few problems in your code:
1) you need to return a pointer to the beginning of the array in count:
return &myInt[0];
or
return myInt; //should suffice.
Then when you initialize myInt2:
int* myInt2 = count();
You can also copy one array into the other:
int myInt2[10];
std::copy(count(), count()+10, myInt2);
Note copying will create a second array using separate memory than the first.
You don't need pointers, references are fine.
int (&count())[10]
{
static int myInt[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
return myInt;
}
int main(int argc, const char * argv[])
{
int (&myInt2)[10] = count();
std::cout << myInt2[3] << "\n\n";
return 0;
}