Eigen Matrix of Vector3d gives strange error - c++

I need container of 3D vectors and tried this:
//typedef Eigen::Matrix<Vector3d, -1, 1> Field3X;
typedef Eigen::Matrix<Vector3d, Dynamic, 1> Field3X;
Field3X vecMat(3);
Vector3d v(1.0,3.0,4.0);
vecMat(0)= v;
vecMat(1) = v;
vecMat(2) = v;
cout << "Here is vecMat:\n" << vecMat << endl;
Calling cout line gives strange error:
Error 3 error C2665: 'log10' : none of the 3 overloads could convert all
the argument types d:\eigen-eigen-
5a0156e40feb\eigen\src\Core\NumTraits.h 34 1
What is better way to have array of Vector3d objects?
p.s. yes I know, I can use stl vector with alignment macro, but which one is better for faster access an manipulations?

The stream output operator << is not defined / overlaoded for the type that you want to display. You can use this instead:
for (int i = 0; i < vecMat.size(); ++i) {
cout << "Here is vecMat(" << i << "):\n" << vecMat(i) << endl;
}

Related

C++ Creating Dynamic 2D Array With One Statement but Without auto

I've seen that a dynamic 2D array in C++ can be created as follows:
auto arr{ new int[nRows][nCols] };
nRows and nCols are compile-time known and the size of the array will not change during runtime.
I've tested what is the type of arr is PAx_i (where x is nCols). But I cannot figure out what to put instead of auto (if I don't want to use it) to create a dynamic 2D array with a single statement.
So, the question: Is it possible in C++ to specify the type of a dynamic 2D array directly (C-style like)? If yes, how?
C++ does not support dynamically-sized raw arrays (aka Variable Length Arrays, or VLAs). Whenever you come across the need for such a dynamic array (how ever many dimensions it may have), you should be immediately thinking of using the std::vector container.
Once properly created, you can use the [] operator (concatenated, for 2-D vectors) in much the same way as you would with raw arrays.
Here's a short code demo that creates a dynamic, 2-dimensional 'array' of integers, using the std::vector class, and initializes all elements with an especially significant, non-zero value:
#include <iostream>
#include <vector>
int main()
{
size_t nCols, nRows;
std::cout << "Enter nRows and nCols: ";
std::cin >> nRows >> nCols;
if (nCols < 2 || nRows < 2) {
std::cout << "Matrix is too small!\n";
return 1;
}
// The following SINGLE LINE declares and initializes the matrix...
std::vector<std::vector<int>> arr(nRows, std::vector<int>(nCols, 42));
std::cout << "nRows = " << arr.size() << "\n";
std::cout << "nCols = " << arr[0].size() << "\n";
for (auto& row : arr) {
for (auto i : row) {
std::cout << i << " ";
}
std::cout << std::endl;
}
// Demo for how to use the "[][]" operator ...
arr[0][0] = arr[nRows - 1][nCols - 1] = 33; // Change 1st and last
std::cout << "------------\n";
for (auto& row : arr) {
for (auto i : row) {
std::cout << i << " ";
}
std::cout << std::endl;
}
return 0;
}
One of the great benefits of using std::vector over new[] is that you don't have to worry about subsequently calling delete[] – the container class takes care of all memory allocation and deallocation internally.
In C++ try to avoid new/delete unless you have no other choice.
Next up is std::make_unique (or std::make_shared).
For dynamic arrays C++ has 'std::vector'
Like this :
#include <vector>
#include <iostream>
int main()
{
// 2x2 vector
std::vector<std::vector<int>> values{ {0,1},{2,3},{4,5} };
std::cout << values[1][1];
return 0;
}
Thusly, vector of vector, in this case the values are uninitialized.
std::vector<std::vector<int>> arr(nRows,std::vector<int>(nCols));
You can also do this with gcc compiler, but its not per standard, and won't work if nRows or nCols is variable in Visual Studio:
int arr[nRows][nCols];
It's better for you to get comfortable with C++ standard library, as it will open up new worlds for you.
Another way:
int *arr = new int[nRow*nCol];
You can then index into the flat buffer like:
arr[0][1]

New C++11 for loop causes "error: ‘begin’ was not declared in this scope" using it for an struct with array

I'm having a struct with an array which is static and want to access the data in that array. Tried to use the new C++11 for loops and also do it without the for loop and just print array[1]. See the second cout in the main function.
I already know that the problem have to do something with the fact that the array in the struct tCalcAngularEstimationFromComplexData_32 is adjusted as a pointer type. Therefore I tried to use for (const auto &arr : &test_data_1) but wasn't able to solve it.
Thanks.
typedef struct tComplex_R {
float real;
float imag;
}tComplex_R;
typedef struct tOutputVRx_R {
float range;
float vel;
tComplex_R AmpLinRx[1];
} tOutputVRx_R;
typedef struct tCalcAngularEstimationFromComplexData_32{
int antennas_azimuth;
int antennas_elevation;
tOutputVRx_R dataset1[32]; //Range Velocity and Complex Data for 32 Antennas
} tCalcAngularEstimationFromComplexData_32;
static tCalcAngularEstimationFromComplexData_32 tCalcAngEstComplexData_dataset_1 = {
5, 90,
{{1, 3, {10, 15}},
{2, 4, {11, 16}}
}
};
int main(){
tCalcAngularEstimationFromComplexData_32 test_data_1 = tCalcAngEstComplexData_dataset_1;
cout << "Range 1: " << test_data_1.dataset1->range << endl;
cout << "Range 2: " << test_data_1.dataset1[1]->range << endl; //Not working
for (const auto &arr : test_data_1) {
cout << "Range: " << arr.dataset1->range << endl;
}
}
Range-based for loops need to have access to the bounds of what you're iterating.
As noted on the relevant cppreference page, there are three ways:
It is an array of known size (which is the case for your dataset1 member)
my_struct::begin() and my_struct::end() are defined
begin(my_struct&) and end(my_struct&) are defined
As for this line:
cout << "Range 2: " << test_data_1.dataset1[1]->range << endl; //Not working
It is because dataset1[1] is not a pointer but a reference, so you don't use -> but . instead.
See a working example on godbolt

How to pair 2D array and integer in the output of the function?

I'm struggling to create multi-variable output from a function: I want to return 2D array sites(16x15) and the integer number N.
I tried:
std::make_tuple here
std:make_pair here
My problem is that I probably do not know how to define a 2D array in the declaration of the function std::pair <int [][],int> correctly.
Piece of code named function.cpp:
#include <iostream>
std::pair <int[16][15],int> sites_diamond()
{
int sites[16][15]={0};
int N=0;
for (int r=0; r<7; r++) {
N=N+1+2*r;
for (int c=0; c<(7-r);c++){
sites[r][c]=0;
sites[15-r][c]=0;
sites[r][14-c]=0;
sites[15-r][14-c]=0;
}
}
N=2*(N+15);
return std::make_pair(sites, N);
}
using namespace std;
int main(){
std::pair <int[16][15], int> result = sites_diamond();
cout << " sites \n"<<result.first<< endl;
cout << "number \n"<<result.second<< endl;
return 0;
}
Error I'm getting:
function.cpp: In function ‘std::pair<int [16][15], int> sites_diamond()’:
function.cpp:21:26: error: could not convert ‘std::make_pair<int (&)[16][15], int&>(sites, N)’ from ‘std::pair<int (*)[15], int>’ to ‘std::pair<int [16][15], int>’
return std::make_pair(sites, N);
Thank you ahead for any suggestions.
I work primarily in Python, but I want to rewrite a code to C++.
You can go with std::array. It is more C++-ish and you don't need to care about memory allocation/deallocation.
std::pair <std::array<std::array<int, 15>, 16>, int> sites_diamond()
{
std::array<std::array<int, 15>, 16> sites;
// ...
return std::make_pair(sites, N);
}
and then the usage would be:
auto result = sites_diamond();
cout << " sites \n" << result.first.size() << endl;
cout << " number \n" << result.second << endl;
As the error is quite explanatory, I will just suggest the solution. Use pointers.
Define your pair like this:
std::pair<int**, int> result;
Of-course, inside your function, change how you define sites:
int **sites;
sites = new int*[16];
for (int i = 0;i < 16;i++)
sites[i] = new int[15];
Regarding
cout << " sites \n"<<result.first<< endl;
I don’t know what are you trying to print here, it's gonna print some random address anyway.
Don’t forget to delete this dynamically allocated memory when you are done.
But all in all, I would just suggest to use something like vectors (2-d vector in this case, leak-proof too) in place of C-styled arrays.

Visual Studio does not show in which line error is

When I am programming in C++ and Visual Studio 2019 throws an error, it shows in which line it was encountered. But when coding with C++ when error is thrown, it does not show in which line exactly it appears. So it makes hard to debug and fix my program. Maybe there are settings that I need to adjust?
C++ error (it point to some 1501 line of installation files that weren't created by me):
vector<int> myVector(2);
cout << myVector[4] << endl;
Errors in both programs in these examples are of a same category: vector (in C++).
Without providing more code and looking at the minimal c++ code you provided:
vector<int> myVector(2);
cout << myVector[4] << endl;
It looks like you have too many elements in myVector in the second line. You will have UB because the [] operator does not allocated more elements. You only declared 2 elements.
Now, when you send your vector to cout you are saying you have 4 which is false.
That is why you are getting the error: "Expression: vector subscript out of range".
You only have two indices 0 and 1, if you define a vector with 2 elements.
Now if you were trying to see the size of your vector you use the .size() function which returns the number of elements in the vector.
vector<int> myVector(2);
cout << myVector.size() << endl;
You could even do something like this with a for loop:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> myVector(2);
std::cout << myVector.size() << std::endl;
for (int i = 0; i < 10; i++)
myVector.push_back(i);
std::cout << myVector.size() << '\n';
return 0;
}

displaying an iterator to a vector

I am working on a project where I am placing an enum into a vector. and I was wondering how I could get functionality like such out of the vector.
for(int ii = 0; ii < thing.getSize(); ii++){
cout << "thing(" << ii << ") = " << toString(thing[ii]) << endl;
}
I've tried about 5 different ways to do this, and none of them seem to work. I have read through MSDN vector (vector::end() seemed the most helpful until it said that the operator<< wouldn't accept ii as an iterator.
can somebody help me out? the closest I think I got was
vector<int>::iterator ii;
for(ii = things.begin(); ii != things.end(); ii++){ //764
cout << "thing(" << (int)ii << "): " << toString(things[ii]) << endl; //765
}
but this throws errors that either don't make sense or I can't figure out how to solve.
1>c:\...\Project.cpp(764): error C2678: binary '!=' : no operator found which takes a left-hand operand of type 'std::_Vector_iterator<_Myvec>' (or there is no acceptable conversion)
1>c:\...\Project.cpp(765): error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'std::_Vector_iterator<_Myvec>' (or there is no acceptable conversion)
1>c:\...\Project.cpp(765): error C2679: binary '[' : no operator found which takes a right-hand operand of type 'std::_Vector_iterator<_Myvec>' (or there is no acceptable conversion)
The correct generic way to do this is
for(std::vector<int>::const_iterator ii=things.begin();
ii != things.end(); ++ii)
{
std::cout << "thing("
<< std::distance(things.begin(), ii)
<< "): " << *ii << std::endl;
}
is by dereferencing the iterator and using std::distance to get the distance from the beginning.
further more it is generally considered bad to import an entire namespace it is better to either have explicit using statements or a preferably prefix types with it's namespace.
It is also generally preferrable to use the prefix increment operator for iterators.
Also unless you are doing some interesting formatting there is no need to apply 'toString' to an int. As it has a stream operator defined for it.
Try:
cout << "thing(" << (ii - things.begin()) << "): " << toString(*ii) << endl;
Iterators behave pretty much like pointers: they indicate the position of the value and you need to dereference them to get the value:
std::cout << *ii;
things has to be declared as:
vector < int > things;
You can enter your values into the vector like so:
things.push_back( 1 );
things.push_back( 2 );
Then you iterate like this:
for ( vector < int >::iterator i = things.begin(); i != things.end(); ++i )
{
cout << "things( " << ( i - things.begin() ) << " ): " << toString( *i ) << endl;
}