How to use lambda in for_each? - c++

I am trying to use for_each instead of the normal for loop. However, since I am new to C++11, I am kind of stuck. My intent here is to use for_each and lambda expression together. Any ideas ? I am using visual studio 2010.
Regards,
Atul
Here is the code.
#include "stdafx.h"
#include <algorithm>
#include <memory>
#include <vector>
#include <iostream>
using namespace std;
struct Point
{
union
{
double pt[3];
struct {double X,Y,Z;};
struct {double x,y,z;};
};
Point(double x_,double y_,double z_)
:x(x_),y(y_),z(z_)
{}
Point()
:x(0.0),y(0.0),z(0.0)
{}
void operator()()
{
cout << "X coordinate = " << x << endl;
cout << "Y coordinate = " << y << endl;
cout << "Z coordinate = " << z << endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<Point> PtList(100);
//! the normal for loop
for(int i = 0; i < 100; i++)
{
// Works well
PtList[i]();
}
//! for_each using lambda, not working
int i = 0;
for_each(PtList.begin(),PtList.end(),[&](int i)
{
// Should call the () operator as shown previously
PtList[i]();
});
//! for_each using lambda, not working
Point CurPt;
for_each(PtList.begin(),PtList.end(),[&CurPt](int i)
{
cout << "I = " << i << endl;
// should call the() operator of Point
CurPt();
});
return 0;
}

The third parameter of for_each is a function to apply to each element, not to each index. Otherwise, what would be the point of using that over a traditional loop?
So, instead of an int parameter, it takes a Point parameter. And now there's no reason to capture anything, because a reference to PtList is unnecessary.
// Should make operator() const as it doesn't modify anything
for_each(PtList.begin(),PtList.end(),[](Point const& p)
{
p();
});

Your std::for_each is obviously wrong. The type of the argument to the lamba should be Point, or Point const& depending on what you want to do, and what you're allowed to do.
It should be this:
int count = 0;
for_each(PtList.begin(),PtList.end(), [&](Point const & p)
{
cout <<"No. " << ++count << endl;
p();
});
Make your operator() a const member function.

Related

Access map element via pointer in C++

I switched from c to c++ recently and just can't figure out what I'm doing wrong here.
I would like to access and set the member of a map via another function.
Here is my example which you can just copy to cpp.sh or so if you like
#include <iostream>
#include <map>
using namespace std;
struct test{
int i;
int j;
};
void addValues(test* val){
if (val == NULL){
val = new test();
cout<<"new";
}
val->i = 10;
val->j = 12;
}
void printVal(test* val){
cout<<"finish " << val->i << " " << val->j;
}
int main()
{
map<string, test*> bla = {{"test1",NULL}};
addValues(bla.at("test1"));
printVal(bla.at("test1"));
return 0;
}
code from my project is a little bit more complex but it's basically this problem. I created a test in addValues() and have not deleted it. Why am I not able to print this value in printVal()? What am I missing?
Thanks in advance!
Parameters are passed by value. Pointers are no exception to that. Your addValues modifies a local copy of the pointer when a nullptr is passed. Modifying that local copy does not affect the pointer in the map. Pass the pointer by reference:
void addValues(test*& val){
if (val == nullptr){
val = new test();
cout<<"new";
}
val->i = 10;
val->j = 12;
}
Or better yet, do not use raw pointers in the first place. Moreover, consider to write a constructor that initializes the members of test instead of relying on the caller to initialize them.
Example :
#include <iostream>
#include <map>
//using namespace std; NO teach yourself not to do this.
struct test
{
int i = 0; // <== in c++ you can initialize values of structs
int j = 0;
};
// this instead of printVal
std::ostream& operator<<(std::ostream& os, const test& t)
{
os << "i = " << t.i << ", j = " << t.j << "\n";
return os;
}
int main()
{
std::map<std::string, test> map =
{
{"test1",{1,1}},
{"test2",{2,2}},
};
// loop over all entries in the map
// range based for loop.
// each entry in the map is a key,value pair (not they key, not the value but a pair)
// https://en.cppreference.com/w/cpp/language/range-for
std::cout << "range based for over keyvalue pairs\n";
for (const auto& kv : map)
{
// note kv.second is where we use operator<< from earlier.
std::cout << "Key : " << kv.first << ", value : " << kv.second << "\n";
}
std::cout << "\n";
// structured bindings make code more readable
// https://en.cppreference.com/w/cpp/language/structured_binding
std::cout << "range based for using structured bindings \n";
for (const auto& [key, value] : map)
{
std::cout << "Key : " << key << ", value : " << value <<"\n";
}
std::cout << "\n";
return 0;
}

How to I send the Map values to the class

#include <iostream>
#include <memory>
#include <initializer_list>
#include <cassert>
#include <map>
template <typename T>
class Matrix
{
private:
int i,j;
T value;
std::map<std::array<int, 2>,double> Mat;
public:
Matrix():i(0),j(0)
{
std::cout<<"Empty boi called"<<std::endl;
}
Matrix(int row, int column)
{
std::cout<<"Main boi called"<<std::endl;
}
// I'm not really sure where to plug this code in
// In the main function, this code works but not really in class
for (std::map<std::array<int, 2>,int>::iterator it=Mat.begin(); it!=Mat.end(); ++it)
{
i = it->first[0];
j = it->first[1];
value = it->second;
std::cout << "["<< it->first[0] <<","<<it->first[1]<<"]"<< " => " << it->second << '\n';
}
};
int main()
{
std::map<std::array<int, 2>,int> Mat;
Mat[{1,5}]=20;
Mat[{2,6}]=30;
for (std::map<std::array<int, 2>,int>::iterator it=Mat.begin(); it!=Mat.end(); ++it)
std::cout << "["<< it->first[0] <<","<<it->first[1]<<"]"<< " => " << it->second << '\n';
// The same code done in main function is what I want to do in the class
Matrix<double> M(10,10);
M{[1,1]} = 3.14; // This returns an error
return 0;
}
As seen, the mapping is possible when its directly in the main function, but I want to send multiple positions of M to the class and have it initialised. But completely unable to do so. Tried looking in a lot of places to no avail.

A memory error with recursion

This is my code. The program gets some point coordinates and it should enumerate all paths (It should be more complicated in future but this is the essence)
#include <iostream>
#include <utility>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cmath>
using namespace std;
struct Point {
Point () {};
Point (const int &x_, const int &y_) : x{x_}, y{y_} {};
int x, y;
};
double distance(const Point &a, const Point &b) {
return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
}
struct Path {
vector<Point> points;
double length;
Path(vector<Point> &p) : points{p}, length{0.0} {};
void add_point(Point &p) {
length += distance(p, points.back());
points.push_back(p);
}
};
vector<Path*> enumerate_paths(vector<Point> &coordinates) {
// assuming coordinates is not empty
vector<Path*> result;
unsigned int size = coordinates.size();
if (size == 1) {
result = {new Path{coordinates}};
return result;
}
vector<Point> coordinates_copy;
vector<Path*> recursion_result;
for(unsigned int i = 0; i < size; ++i) {
cout << "cycle start" << endl << flush;
coordinates_copy = coordinates;
coordinates_copy.erase(coordinates.begin()+i);
// Get results for one coordinate skipped
recursion_result = enumerate_paths(coordinates_copy);
cout << "recursion done" << endl << flush;
// Add the coordinate to each of those results
for_each(recursion_result.begin(), recursion_result.end(),
[&](Path *path) {
path->add_point(coordinates.at(i));});
// Concatenate with previous results
copy(recursion_result.begin(), recursion_result.end(), back_inserter(result));
cout << "cycle end" << endl << flush;
}
cout << "escape recursion" << endl << flush;
return result;
}
int main() {
vector<Point> coordinates = { Point(0,0), Point(1,0), Point(0,1), Point(1,1)};
auto paths = enumerate_paths(coordinates);
cout << "done!" << flush;
}
I believe that the idea of the algorithm is correct, but I'm getting a memory error that I don't understand - double free or corruption (out). I compile with g++ -Wall -std=c++11 without error. What is going on here? Can somebody help?
I can't promise you this is the only problem, but right here:
coordinates_copy.erase(coordinates.begin()+i);
You are eraseing using an iterator from a different vector. Change coordinates.begin() to coordinates_copy.begin().
Also, delete the memory you new ;). Or better yet, switch to smart pointers. Or even forget about pointers entirely and lean on vector's move constructor and the return value optimization instead.

Trouble with types when passing vector to function in c++

I am starting a c++ class having never done anything in the language before, and I'm pretty confused by vectors.I made a toy example and I don't quite understand why the doubles that I put into a vector become vector's. Here is the code:
#include <iostream>
#include <vector>
using namespace std;
vector<double> a;
void func(vector<double> *);
int main()
{
for (int i = 0; i < 100; i++)
{
a.push_back(double(i));
}
func(&a);
return 0;
}
void func(vector<double> *vec)
{
cout << double(vec[0]) << endl;
return;
}
It ends up giving me this error:
error: cannot convert 'vector' to 'double' without
a conversion operator
and I have no idea what that means. What exactly is happening here and how can I cast a vector into a double?
You don't need to mix using pointers * with std::vector.
Method 1 (not recommended):
Change
cout << double(vec[0]) << endl;
to
cout << double((*vec).at(0)) << endl;
Method 2:
Change
void func(vector<double> *vec)
to
void func(vector<double> vec)
or
void func(const vector<double> &vec)
Change
func(&a);
to
func(a);
The reason for the actual error is more due to a misunderstanding of pointers than vectors . The problem is that you are passing a pointer to a vector. If you want to use the vector itself, then you would do:
cout << (*vec)[0] << endl;
* will dereference the pointer to get the actual vector instance rather than an index into an address which is what you were doing before.
But, as pointed out in the other answer, it is safer just to pass the vector by reference (or better yet, const reference):
void func(const vector<double>& vec)
{
cout << vec[0] << endl;
return;
}
then call as:
func(a);
Another way to use vectors is with a std::vector< TYPE >::const_iterator like this;
#include <iostream>
#include <vector>
double func(std::vector<double>::const_iterator iter);
int main()
{
std::vector<double> vec;
for (double i = 0.0; i < 1; i += 0.1){
vec.push_back(i);
}
std::cout<< func(vec.begin()+3) << " "
<< func(vec.begin()+6) << std::endl;
return 0;
}
double func(std::vector<double>::const_iterator iter){
return *iter;
}
outputs;
0.3 0.6

Sort std::vector<myclass> in one line using sort function from STL

Question is about sorting std::vector<myclass> using function sort from STL's algorithms class.
Standard way is : sort(v.begin(), v.end(), &myfunct)
where myfunct is:
bool myfunct( myclass first, myclass second ) {
if (first.value < second.value)
return true;
else return false;
}
Approach above takes more than one line. I am curious how to do it in one line. Is it possible define function that compares myclass objects inside sort function? May be somehow use this (a < b) ? a : b. I remember that there is something like this in C#, but I forgot how is it called. Is it possible to do in C++.
First, you can just return first.value < second.value but this doesn't get rid of the function. In C++2011 you can use a lambda function:
std::sort(begin, end, [](myclass const& f, myclass const& s){ return f.value < s.value; });
Without C++2011 I think you'll need a function object because there isn't anything which projects your class to the value you actually want to compare.
BTW, you definitely want to pass everything but the most trivial objects by reference to your comparison function.
You could use boost::lambda and boost::lambda::bind (with boost lambda placeholders)
std::sort(vec.begin(), vec.end(),
boost::lambda::bind(&A::a, boost::lambda::_1)
<
boost::lambda::bind(&A::a, boost::lambda::_2));
sort passes 2 values to the comparison function so you need to compare those 2 values. The bind part of code just selects variable a from the struct A from each structures being compared (referenced by _1 and _2).
Example code:
#include <iostream>
#include <algorithm>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/array.hpp>
struct A
{
A() : a(0), b(0) {}
int a;
int b;
};
std::ostream & operator<<(std::ostream & os, A & a)
{ return os << a.a << ":" << a.b; }
int main()
{
boost::array<A,5> vec;
std::fill(vec.begin(),vec.end(),A());
vec[0].a = 1;
vec[1].a = 3;
vec[2].a = 4;
vec[3].a = 0;
vec[4].a = 2;
std::for_each(vec.begin(),vec.end(), std::cout << boost::lambda::_1 << ' ');
std::cout << std::endl;
std::sort(vec.begin(), vec.end(),
boost::lambda::bind(&A::a, boost::lambda::_1)
<
boost::lambda::bind(&A::a, boost::lambda::_2));
std::for_each(vec.begin(),vec.end(), std::cout << boost::lambda::_1 << ' ');
std::cout << std::endl;
}
Output:
1:0 3:0 4:0 0:0 2:0
0:0 1:0 2:0 3:0 4:0
why not copy the vector into a set:
std::copy(v.begin(),v.end(),std::inserter(s,s.end()));
Now the elements in the set are sorted in ascending order and use set now.
A one liner call to sort() : sort(my_vector_of_class_object.begin(),my_vector_of_class_object.end(),compare);
Code of a working demo of a "sort vector of class objects" is provided below:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
class my_Class
{
public:
my_Class(int r,int n, int s):rollno(r),name(n),status(s) { }
int getRollno() const { return rollno;}
int getName() const { return name;}
int getStatus() const { return status;}
private:
int rollno;
int name;
int status;
};
bool compare(const my_Class& x, const my_Class& y) {
return x.getRollno() < y.getRollno();
}
int main()
{
vector<my_Class> my_vector_of_class_object;
vector<my_Class>::const_iterator iter;
my_Class s1(10,20,30);
my_Class s2(40,50,60);
my_Class s3(25,85,9);
my_Class s4(1,50,2);
my_Class s5(90,70,90);
my_Class s6(85,85,3);
my_Class s7(20,6,89);
my_Class s8(70,54,22);
my_Class s9(65,22,77);
my_vector_of_class_object.push_back(s1);
my_vector_of_class_object.push_back(s2);
my_vector_of_class_object.push_back(s3);
my_vector_of_class_object.push_back(s4);
my_vector_of_class_object.push_back(s5);
my_vector_of_class_object.push_back(s6);
my_vector_of_class_object.push_back(s7);
my_vector_of_class_object.push_back(s8);
my_vector_of_class_object.push_back(s9);
cout <<"Before vector sort \n";
for(iter=my_vector_of_class_object.begin(); iter!=my_vector_of_class_object.end();++iter)
std::cout << (*iter).getRollno() << '\t' << (*iter).getName() << '\t' << (*iter).getStatus() << '\n';
cout <<" \n\n";
sort(my_vector_of_class_object.begin(),my_vector_of_class_object.end(),compare);
cout <<"After vector sort \n";
for(iter=my_vector_of_class_object.begin(); iter!=my_vector_of_class_object.end();++iter)
std::cout << (*iter).getRollno() << '\t' << (*iter).getName() << '\t' << (*iter).getStatus() << '\n';
cout <<" \n\n";
return 0;
}