Inserters in C++ confusion - c++

So I dont understand how to use inserters in this situation. I know what are inserters, I know about std::front_inserter and std::back_inserter and std::inserter but I am confused about this problem which I will present now.
I need to make function, which will transform elemets of vector and put them in deque(or vector nevermind, its "generic" function anyway).
That function has 5 parameters, which one of them is another function(which can have only one parameter, it is not specified what type(i mean it can be reference,iterator,pointer...... whatever)).
If my vector is:
std::vector<int> v={1,2,3,4,5};
I need to make some modification, with lambda function, which will make my deque have elements like this:
25 16 9 4 1
So you see that first element of deque is last element of vector ^2 (you can see what I want to do).
So my question is:
How can the problem be done using inserters? I mean should I somehow put inserter in lambda fucntion? Maybe lambda should be like this:
[](int x) {
x=x*x;
std::front_inserter(q);
}
I was thinking about this but then I dont understand how will this lambda work when I send it as parameter of this "big" function? How it will know what is q inside big function?
I hope you understand what I want to do.
Here is example.
So I have to make some function, and this is prototype(lets say it is void):
typename<template Type1, template Type2>
void Fun(Type1 p1,Type1 p2,Type2 p3,Type2 p4,void (*f)(std::remove_reference<decltype(*p1)>::type) );
Lets say that I have the following code in main:
int main() {
std::vector<int> v={1,2,3,4,5};
std::deque<int> d(5);
Fun(v.begin(),v.end(),d.begin(),d.end(), /* some lambda function */);

If you're only interested in the transformation, not in implementing a function with that type,
std::deque<int> d;
std::transform(v.begin(), v.end(), std::front_inserter(d), [](int x){return x * x;});
or
std::deque<int> d;
std::transform(v.rbegin(), v.rend(), std::back_inserter(d), [](int x){return x * x;});

Related

Range based for loop through non-const literal c++

Compiler context: I am compiling with GDB v8.3 Ubuntu with options g++ -Im -O2 -std=c++0x.
Very frequently I need to complete some loop for two or three objects so I use wrap the expression in a range based for loop with a containing litteral.
In Python3 this would look like:
a = [1,2,3]
b = [4,5,6]
for v in (a,b):
func(v)
In c++ this obviously isn't so simple. As far as I am aware, using {a,b} creates some type of initializer list, therefor casting does not properly work. In my attempts I come to something of this sort, but do no understand how I would properly pass by reference and also have it be mutable, as my compiler complains this is neccessarily const.
vector<int> a {1,2,3};
vector<int> b {4,5,6};
for(auto& v: {a,b}) // error non-const
func(v);
Based on your python program, it appears that you want to iterate through all the vectors, but with a mutable reference to each vector. You can do this by using pointers:
for(auto *v: {&a, &b}) // iterate over pointers to the vectors
func(*v); // dereference the pointers to get mutable
// references to the vectors
Here's a demo.
int x,y;
for(int& i:{std::ref(x),std::ref(y)}){
i=7;
}
auto& won't work, and you do have to repeat std::ref for each element.
Another trick is:
auto action=[&](auto&foo){
// code
};
action(v1);
action(v2);
You can write:
void foreach_arg(auto&&f, auto&&...args){
((void)f(decltype(args)(args)),...);
}
or pre-c++20 versions in more characters, then:
auto action=[&](auto&foo){
// code
};
foreach_arg(action, v1, v2);
If you want the arguments mentioned first, you can do:
auto foreacher(auto&&...args){
return [&](auto&&f){
((void)f(decltype(args)(args)),...);
};
}
and get:
foreacher(v1,v2)([&](auto&v){
// loop body
});
apologies for any typos. Just writing insomnia-code, untested as yet.
decltype thing is a short std::forward equivalent in this case (with auto&& args; with some other declarations it doesn't work).
auto arguments to functions are a c++20 thing.
Then,... is comma-fold execute, a c++17 thing.
auto arguments to lambdas are a c++14 thing.
All can be replaced with c++11 constructs (in this case) at the cost of a lot more verbosity.

Calling recursive function in push_back

I am writing a function to populate a vector in ascending order using values from a binary search tree. I am also trying to keep the run time of this function to O(n). I am thinking I will need to call a recursive function that traverses the bst and gets the numbers in ascending order. I am confused about how to use the results from the recursive function. Is it okay to use a recursive function inside of push back like this?
void vector_function(){
std::vector<int> *v = new std::vector<int>();
v.pushback(recursive_function(node *p));
}
for example if the Binary Search tree had values 5, 3, 4, 7 the resulting vector would have 3, 4, 5, 7
I am confused about how to use the results from the recursive function. Is it okay to use a recursive function inside of push back like this?
I can think of two ways of doing that.
Option 1
Change recursive_function to also accept a reference to a std::vector<int>. Update its implementation to push_back elements to the vector appropriately.
Pass the vector to recursive_function when calling it.
void recursive_function(node* p, std::vector<int>& v)
{
// When appropriate...
v.push_back(p.data);
}
and use it as
void vector_function(){
std::vector<int> v;
recursive_function(p, v));
}
Option 2
Change recursive_function to also accept a std::function. Update its implementation to call the std::function with the value of the node appropriately. Use a lambda function that can be converted to a std::function that recursive_function accepts in the call to the function. Take care of calling push_back on the vector in the lambda function with the argument passed to it.
void recursive_function(node* p, std::function<void(int)> f)
{
// When appropriate...
f(p.data);
}
and use it as
void vector_function(){
std::vector<int> v;
recursive_function(p, [&v](int e) -> void { v.push_back(e); });
}

C++11, copying just one field into a vector

Say I have the following struct in C++
struct Foo {
double a;
int b;
};
And say I have a parameter to some function declared as follows:
const std::initializer_list<Foo> &args;
Is there an concise way to extract just one field from the elements in args to get, for instance, just an std::vector containing each b field from the original args list?
Of course, I know I could do this by just explicitly writing it out as a loop:
std::vector<int> result;
for(auto &x:args) {
result.push_back(x.b);
}
... but given that I can copy an entire initializer_list of any type to a like-typed vector in a single line of C++, just using functions like std::copy and std::back_inserter, I am wondering if there is a more elegant way to do this as well, using stl or C++11 facilities that may already exist.
You could use std::transform and add elements to the vector via std::back_inserter:
std::transform(std::begin(args), std::end(args), std::back_inserter(result),
[] (const Foo & foo) { return foo.b; });
If you find the lambda too verbose you can use std::mem_fn instead (credit goes to #StoryTeller).
std::transform(std::begin(args), std::end(args), std::back_inserter(result), std::mem_fn(&Foo::b));
But then again, your approach isn't necessary bad since it's pretty readable and does the job just fine (might have some performance issues tho).
One solution can be using linq++ like the following:
shared_ptr<vector<Foo>> foo_list;
// suppose foo_list is being filled
shared_ptr<vector> bs = from(foo_list).select(&_1 ->* &Foo::b).get();

How can I use lambda in vector of type int? [duplicate]

This question already has an answer here:
How to use lambda to erase empty vector cells?
(1 answer)
Closed 9 years ago.
I have a vector:
std::vector<int> graphPred(tot_lines);
that I set to various values but when the input is done I would like to eliminate empty cells I tried:
graphPred.erase(std::remove_if(graphPred.begin(), graphPred.end(),
[](const int graphPred){return graphPred.empty();}),
graphPred.end());
but the compiler is complaining that "expression must be a class type"
Is there a problem with my syntax or another way to accomplish my goal?
"yes they are 0"
So use this:
graphPred.erase(std::remove_if(graphPred.begin(), graphPred.end(),
[](const int x){return x==0;}),
graphPred.end());
Your lambda function
[](const int graphPred){return graphPred.empty();}
is using empty on an int, which is wrong, member functions are called on class, and that's what the error all about
What you wrote does not make sense: const int graphPred "shadows" the graphPred outside (which wouldn't be captured anyway, because the square brackets are empty). It is calling empty on an int that triggers the error that you see.
Moreover, if graphPred is empty(), there is nothing to erase from it, so you need some sort of a meaningful logic expression in your lambda.
This should work - it will erase all even numbers from the vector:
graphPred.erase(
std::remove_if(
graphPred.begin()
, graphPred.end()
, [](const int n){return n % 2 == 0;}
)
, graphPred.end()
);
Here is a demo on ideone.
You declear the lambda as:
[](const int graphPred){return graphPred.empty();}
So graphPredis a const int not a class. You can not cal graphPred.empty()

Multiply vector elements by a scalar value using STL

Hi I want to (multiply,add,etc) vector by scalar value for example myv1 * 3 , I know I can do a function with a forloop , but is there a way of doing this using STL function? Something like the {Algorithm.h :: transform function }?
Yes, using std::transform:
std::transform(myv1.begin(), myv1.end(), myv1.begin(),
std::bind(std::multiplies<T>(), std::placeholders::_1, 3));
Before C++17 you could use std::bind1st(), which was deprecated in C++11.
std::transform(myv1.begin(), myv1.end(), myv1.begin(),
std::bind1st(std::multiplies<T>(), 3));
For the placeholders;
#include <functional>
If you can use a valarray instead of a vector, it has builtin operators for doing a scalar multiplication.
v *= 3;
If you have to use a vector, you can indeed use transform to do the job:
transform(v.begin(), v.end(), v.begin(), _1 * 3);
(assuming you have something similar to Boost.Lambda that allows you to easily create anonymous function objects like _1 * 3 :-P)
Modern C++ solution for your question.
#include <algorithm>
#include <vector>
std::vector<double> myarray;
double myconstant{3.3};
std::transform(myarray.begin(), myarray.end(), myarray.begin(), [&myconstant](auto& c){return c*myconstant;});
I think for_each is very apt when you want to traverse a vector and manipulate each element according to some pattern, in this case a simple lambda would suffice:
std::for_each(myv1.begin(), mtv1.end(), [](int &el){el *= 3; });
note that any variable you want to capture for the lambda function to use (say that you e.g. wanted to multiply with some predetermined scalar), goes into the bracket as a reference.
If you had to store the results in a new vector, then you could use the std::transform() from the <algorithm> header:
#include <algorithm>
#include <vector>
int main() {
const double scale = 2;
std::vector<double> vec_input{1, 2, 3};
std::vector<double> vec_output(3); // a vector of 3 elements, Initialized to zero
// ~~~
std::transform(vec_input.begin(), vec_input.end(), vec_output.begin(),
[&scale](double element) { return element *= scale; });
// ~~~
return 0;
}
So, what we are saying here is,
take the values (elements) of vec_input starting from the beginning (vec_input.begin()) to the end (vec_input.begin()),
essentially, with the first two arguments, you specify a range of elements ([beginning, end)) to transform,
range
pass each element to the last argument, lambda expression,
take the output of lambda expression and put it in the vec_output starting from the beginning (vec_output.begin()).
the third argument is to specify the beginning of the destination vector.
The lambda expression
captures the value of scale factor ([&scale]) from outside by reference,
takes as its input a vector element of type double (passed to it by std::transform())
in the body of the function, it returns the final result,
which, as I mentioned above, will be consequently stored in the vec_input.
Final note: Although unnecessary, you could pass lambda expression per below:
[&scale](double element) -> double { return element *= scale; }
It explicitly states that the output of the lambda expression is a double. However, we can omit that, because the compiler, in this case, can deduce the return type by itself.
I know this not STL as you want, but it is something you can adapt as different needs arise.
Below is a template you can use to calculate; 'func' would be the function you want to do: multiply, add, and so on; 'parm' is the second parameter to the 'func'. You can easily extend this to take different func's with more parms of varied types.
template<typename _ITStart, typename _ITEnd, typename _Func , typename _Value >
_ITStart xform(_ITStart its, _ITEnd ite, _Func func, _Value parm)
{
while (its != ite) { *its = func(*its, parm); its++; }
return its;
}
...
int mul(int a, int b) { return a*b; }
vector< int > v;
xform(v.begin(), v.end(), mul, 3); /* will multiply each element of v by 3 */
Also, this is not a 'safe' function, you must do type/value-checking etc. before you use it.