C++11 std::array slice - c++

I have a matrix like this:
array<array<double, DISMAX>, DISMAX> Md;
and a vector like this:
array<double, DISMAX> matrixLine;
DISMAX is a constant.
My question: How can I copy that vector to one line of the matrix without using a for loop? Is it possible?

The simplest method is to do the obvious:
Md[0] = matrixLine;
There is still a loop but the std::array hides the details.

Copy assignment, e.g., Md[0] = matrixLine, should work just fine.

Related

Convert std::vector<double> to Eigen::ArrayXd in c++?

how can I convert a vector to an eigen arrayxd in c++?
The only way I found involve doing:
Eigen::ArrayXd newEigen = Eigen::ArrayXd::Zero(oldVector.size());
and then making a loop to replace each element individually. Is there a better way?
I tried a loop. expecting simple way to copy the data, like:
Eigen::ArrayXd newEigen(oldVector.data());
While this is probably the most commonly asked question in the [eigen] tag, a surprising number of answers are not optimal. So here is the shortest, cleanest version:
Eigen::ArrayXd newEigen = Eigen::ArrayXd::Map(
oldVector.data(), static_cast<Eigen::Index>(oldVector.size()));
If you don't want to copy the data, an Eigen::Map borrows the data in the vector so you can access or change it in-place.
Eigen::Map<Eigen::ArrayXd> mapped(
oldVector.data(), static_cast<Eigen::Index>(oldVector.size()));
Eigen::Map is to Eigen::Array what std::string_view is to std::string if that helps explaining.

Transform data from vector to other with no default constructor

I used to use this way to copy data with some changes from container to container:
std::vector<Tsrc> source{Tsrc(),Tsrc(2),Tsrc(3),Tsrc(4)};
std::vector<Tdst> dst(source.size());
std::transform(begin(source),end(source),begin(dst),[](Tsrc& item){
return do_something(item);
}
First of all, is the previous code standard and clean? any enhancing may be applied?
Secondly, I now want to do the same but for a Tdst that does not have a default constructor. So, the above code will not work. I replaced it with:
std::vector<Tsrc> source{Tsrc(),Tsrc(2),Tsrc(3),Tsrc(4)};
std::vector<Tdst> dst;
dst.reserve(source.size());
for(auto& item:dst){
dst.emplace_back(do_something(item));
}
Is it the right way to do it? any advice?
What you are doing looks fine. You can avoid the explicit loop by using std::back_inserter. Also, since the elements of the original range aren't being modified the lambda's parameter should be made const:
dst.reserve(source.size());
std::transform(begin(source), end(source), back_inserter(dst),
[](const Tsrc& item){return do_something(item);});

Uniform initialization with Eigen dynamic types

I'm trying to learn the Eigen C++ library, and was wondering if there is some nice shorthand for initializing dynamic vectors and matrices. It would be really nice to write something like you would using a std::vector
std::vector<int> myVec = {1,2,3,6,5,4,6};
i.e.
VectorXi x = {1,2,3,4,7,5,7};
The closest (ugly) equivalent I can find involves Map . .
int xc[] = {2,3,1,4,5};
Map<VectorXi> x(xc,sizeof(xc)/sizeof(xc[0]));
What other initialization methods are there?
By the code you showed, you are OK in writing const items. So maybe you can do something like
std::vector<int> vec;
const int init_vec[5] = {1,2,3,4,5}
vec.assign(init_vec, init_vec + 5);
See this post of how use array to populate vectors.
EDIT: Correct a wrong link formating.
For fixed size matrices/vectors, you can use the comma initializer:
Matrix3f m;
m<<1,2,3,4,5,6,7,8,9;
I can't test it right now, but it should work similarly for your situation:
VectorXi x(5);
x << 2,3,1,4,5;
If it does not, you could use a temporary Vector, fill it with the five elements using the comma initializer and then assign it to the VectorXi.
edit:
You might also be interested in this page: Eigen: Advanced Initialization

std::list of boost::arrays

I ran into some trouble while using a list of arrays.
So to clear things up I do know that I can't have a std::list containing arrays.
I am using boost::array to be able to do that.
Currently I prototype all datatypes needed for my pathfinding algorithm and test them for speed and cache coherence.
typedef boost::array<int,2> VertexB2i;
typedef std::list<VertexB2i> VertexList;
These types are not used for pathfinding, they are simply easier to use then all the real c++ arrays and flags for the pathfinder, so they are just used to generate a navigation mesh.
(I also know I could use a stl::pair instead boost::array in this case, but I want to keep the generated data as similar to the pathfinders data as possible, so I don't have to deal with two totally different interfaces the whole time)
VertexList* vl = new VertexList();
vl->push_back({{8,28}}); // this does not work, why?
So while setting up some testing data for these two data-types, I noticed that the commented line does not work, although this does work:
VertexList* vl = new VertexList();
VertexB2i ver1 = {{8,28}};
vl->push_back({ver1}); // works
So to sum it up:
Is there anyway to pushback a "VertexB2i" without declaring it separte first?
General advices?
std::array (or boost::array) is an aggregate type. In C++98/03 it can only be initialized in the declarator:
std::array<int, 2> arr = { 1, 2 };
thelist.push_back(arr); // makes a copy
In C++11, you can use uniform initialization to create temporaries as well:
std::list<std::array<int,2>> l;
l.push_back(std::array<int,2>{{2,3}}); // maybe copy
l.emplace_back(std::array<int,2>{{2,3}}); // maybe copy, probably optimized out

Adding to a vector of pair

I have a vector of pair like such:
vector<pair<string,double>> revenue;
I want to add a string and a double from a map like this:
revenue[i].first = "string";
revenue[i].second = map[i].second;
But since revenue isn't initialized, it comes up with an out of bounds error. So I tried using vector::push_back like this:
revenue.push_back("string",map[i].second);
But that says cannot take two arguments. So how can I add to this vector of pair?
Use std::make_pair:
revenue.push_back(std::make_pair("string",map[i].second));
IMHO, a very nice solution is to use c++11 emplace_back function:
revenue.emplace_back("string", map[i].second);
It just creates a new element in place.
revenue.pushback("string",map[i].second);
But that says cannot take two arguments. So how can I add to this vector pair?
You're on the right path, but think about it; what does your vector hold? It certainly doesn't hold a string and an int in one position, it holds a Pair. So...
revenue.push_back( std::make_pair( "string", map[i].second ) );
Or you can use initialize list:
revenue.push_back({"string", map[i].second});
Read the following documentation:
http://cplusplus.com/reference/std/utility/make_pair/
or
http://en.cppreference.com/w/cpp/utility/pair/make_pair
I think that will help. Those sites are good resources for C++, though the latter seems to be the preferred reference these days.
revenue.push_back(pair<string,double> ("String",map[i].second));
this will work.
You can use std::make_pair
revenue.push_back(std::make_pair("string",map[i].second));
Try using another temporary pair:
pair<string,double> temp;
vector<pair<string,double>> revenue;
// Inside the loop
temp.first = "string";
temp.second = map[i].second;
revenue.push_back(temp);
Using emplace_back function is way better than any other method since it creates an object in-place of type T where vector<T>, whereas push_back expects an actual value from you.
vector<pair<string,double>> revenue;
// make_pair function constructs a pair objects which is expected by push_back
revenue.push_back(make_pair("cash", 12.32));
// emplace_back passes the arguments to the constructor
// function and gets the constructed object to the referenced space
revenue.emplace_back("cash", 12.32);
As many people suggested, you could use std::make_pair.
But I would like to point out another method of doing the same:
revenue.push_back({"string",map[i].second});
push_back() accepts a single parameter, so you could use "{}" to achieve this!