#Compilng You need g++ 4.9 to compile this code. Follow these steps to install g++-4.9
After installing run the following command to compile
/usr/bin/g++-4.9 -std=c++11 lambda.cpp
#Running
./a.out
#include <iostream> | |
#include <vector> | |
#include <algorithm> | |
/** | |
Example showing the function programming ideas in | |
C++ 11. Features used here are part of standard language. | |
**/ | |
template <typename Collection,typename unop> | |
void for_each(Collection col, unop op){ | |
std::for_each(col.begin(),col.end(),op); | |
} | |
template <typename Collection,typename unop> | |
Collection map(Collection col,unop op) { | |
std::transform(col.begin(),col.end(),col.begin(),op); | |
return col; | |
} | |
template <typename Collection,typename binop> | |
Collection zip(Collection fc,Collection sc,binop op) { | |
std::transform(fc.begin(),fc.end(),sc.begin(),fc.begin(),op); | |
return fc; | |
} | |
template <typename Collection,typename Condition> | |
bool exists(Collection col,Condition con) { | |
auto exist = std::find_if(col.begin(),col.end(),con); | |
return exist != col.end(); | |
} | |
template <typename Collection,typename Predicate> | |
Collection filterNot(Collection col,Predicate predicate ) { | |
auto returnIterator = std::remove_if(col.begin(),col.end(),predicate); | |
col.erase(returnIterator,std::end(col)); | |
return col; | |
} | |
template <typename Collection,typename Predicate> | |
Collection filter(Collection col,Predicate predicate) { | |
auto fnCol = filterNot(col,[predicate](typename Collection::value_type i) { return !predicate(i);}); | |
return fnCol; | |
} | |
int main() | |
{ | |
//helper println | |
auto println = [](const char *message){ std::cout << message << std::endl;}; | |
auto lambda_echo = [](int i ) { std::cout << i << std::endl; }; | |
std::vector<int> col{20,24,37,42,23,45,37}; | |
//call foreach to print the vector | |
println("running foreach"); | |
for_each(col,lambda_echo); | |
// add one to each element | |
println("running map operation"); | |
auto addOne = [] (int i) { return i+1;}; | |
auto returnCol = map(col,addOne); | |
for_each(returnCol,lambda_echo); | |
//zip operation | |
println("running zip operation"); | |
auto zipAdd = [] (int a, int b){ return a+b;}; | |
std::vector<int> secondCol{40,22,22,24,23,45,34}; | |
auto zipCol = zip(col,secondCol,zipAdd); | |
for_each(zipCol,lambda_echo); | |
println("runnig exists"); | |
//prints 1 if true 0 if false | |
std::cout << "value 20 exist= " << exists(col, [] (int value){ return value==20;}) << std::endl; | |
std::cout << "value 43 exist= " << exists(col, [] (int value){ return value==43;}) << std::endl; | |
println("running filterNot"); | |
auto filterCol = filterNot(col,[](int value){ return value==23;}); | |
for_each(filterCol,lambda_echo); | |
println("running filter"); | |
auto filteredCol = filter(col,[](int value){ return value > 30;}); | |
for_each(filteredCol,lambda_echo); | |
} | |
A more stl-ish approach of map with a the additional ability to define a different target container would be
template<typename RET_CONT, typename IT, typename OPERATION>
RET_CONT map(IT begin, IT end, OPERATION op)
{
RET_CONT ret;
std::transform(begin, end, back_inserter(ret), op);
return ret;
}
its usage would then be
std::vector<int> in = { 0, 1, 2, 3 }:
typedef std::list<int> target_cont_type;
target_cont_type out = map<target_cont_type>(in.begin(), in.end(), [] (auto i) { return i * 10; });
Is there a way to generalize your map combinator so that the output collection does not necessarily have the same type as the input? For example, say I want to take a vector of ints and get a vector of vectors of ints. Perhaps I have misunderstood your code or my compiler errors?
Here is my attempt (which generates compiler errors I don't know how to fix):