How to use lambda auto parameters in C++11 - c++

I have a code in C++14. However, when I used it in C++11, it has an error at const auto. How to use it in C++11?
vector<vector <int> > P;
std::vector<double> f;
vector< pair<double, vector<int> > > X;
for (int i=0;i<N;i++)
X.push_back(make_pair(f[i],P[i]));
////Sorting fitness descending order
stable_sort(X.rbegin(), X.rend());
std::stable_sort(X.rbegin(), X.rend(),
[](const auto&lhs, const auto& rhs) { return lhs.first < rhs.first; });

C++11 doesn't support generic lambdas. That's what auto in the lambda's parameter list actually stands for: a generic parameter, comparable to parameters in a function template. (Note that the const isn't the problem here.)
Note: C++14 does support lambdas with auto, const auto, etc. You can read about it here.
You have basically two options:
Type out the correct type instead of auto. Here it is the element type of X, which is pair<double, vector<int>>. If you find this unreadable, a typedef can help.
std::stable_sort(X.rbegin(), X.rend(),
[](const pair<double, vector<int>> & lhs,
const pair<double, vector<int>> & rhs)
{ return lhs.first < rhs.first; });
Replace the lambda with a functor which has a call operator template. That's how generic lambdas are basically implemented behind the scene. The lambda is very generic, so consider putting it in some global utility header. (However do not using namespace std; but type out std:: in case you put it in a header.)
struct CompareFirst {
template <class Fst, class Snd>
bool operator()(const pair<Fst,Snd>& l, const pair<Fst,Snd>& r) const {
return l.first < r.first;
}
};
std::stable_sort(X.rbegin(), X.rend(), CompareFirst());

I know there is an accepted answer, but you can also use decltype in C++11 for this, it looks a bit messy...
stable_sort(X.rbegin(), X.rend(), [](decltype(*X.cbegin()) lhs, decltype(lhs) rhs) { return lhs.first < rhs.first; });
Use cbegin() here as you get the const correct value_type of the container.

Unfortunately, generic lambdas that take auto (whether const or not) is a C++14 only feature.
See here https://isocpp.org/wiki/faq/cpp14-language#generic-lambdas for some more details.

Alternatively you can directly use the value_type typedef of the container with a decltype, like
std::stable_sort(X.rbegin(), X.rend(),
[](const decltype(X)::value_type & lhs,
const decltype(X)::value_type & rhs)
{return lhs.first < rhs.first; }
);

const auto is not supported in C++11 as a lambda parameter (actually generic lambdas are not supported in C++11).
To fix:
using pair_type = std::pair<double, std::vector<int>>;
vector<pair_type> X;
std::stable_sort(X.rbegin(), X.rend(),
[](const pair_type&lhs, const pair_type& rhs)
{ return lhs.first < rhs.first; });

Related

what is custom comparator and how to use it in the sort function in c++?

vector<vector<int>> reconstructQueue(vector<vector<int>> &people) {
auto cmp = [](const vector<int> &a, const vector<int> &b) {
return a[0] > b[0] || (a[0] == b[0] && a[1] < b[1]);
};
sort(people.begin(), people.end(), cmp);
Hey guys can someone explain me the auto cmp... part and how to use it in a sort function any help will be highly appreciated :)
This part of the code is a lambda. In other words, a small function defined locally.
You can make a search for this term for more info.
IN the case of the sort algorithm, you are expected to pass a function taking two arguments and returning true if the first argument is less than the second.
To make it simple, you give an alternative comparison function to use instead of the standard operator< a.k.a. std::less.
Any object having an operator() can be used.
The comparator can be implemented in multiple ways, for eg. a lambda (as in your example) or a callable struct/class.
Just to give you an example for sorting say a vector of std::pair by the second element:
struct Comparator
{
bool operator()(const std::pair<int,int>& lhs, const std::pair<int,int>& rhs)
{
return lhs.second < rhs.second;
}
}
void foo(std::vector<std::pair<int,int> > &v)
{
std::sort(v.begin(), v.end(), Comparator);
}
Alternatively, instead of using a callable struct, you can write foo using lambda as:
void foo(std::vector<std::pair<int,int> > &v)
{
std::sort(v.begin(), v.end(),
[](const pair<int, int>& lhs, const pair<int, int>& rhs)
{
return lhs.second < rhs.second;
} );
}
You can write more advanced comparisons by say capturing some other data and using that for comparisons. Try reading about lambdas.

What is the difference when passing function's reference and lambda expression as arguments?

I am using custom comparators to priority_queue, finding different behaviors. I already knew that stl containers need specific type passing to template declaration.
When using normal functions, it should be:
bool cmp(pair<int, int> &lhs, pair<int, int> &rhs) {
return lhs.first > rhs.first;
}
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> pq1(v.begin(), v.end(), cmp);
But when using lambda, I find the correct way is:
auto comp = [](const pair<int, int>& lhs, const pair<int, int>& rhs){return lhs.second < rhs.second;};
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(comp)> pq2(v.begin(), v.end(), comp);
I referred to decltype but did not come out an opinion. Could someone explain how compiler treats decltype(&function) and decltype(lambda)?
That's because lambda expressions create an object (of an anonymous class).
If you use &comp then you get a pointer to the object, which is not callable.
The lambda you have is basically equivalent to
struct
{
bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs)
{
return lhs.second < rhs.second;
}
} comp;

Construction a vector from the concatenation of 2 vectors

Is there a way to construct a vector as the concatenation of 2 vectors (Other than creating a helper function?)
For example:
const vector<int> first = {13};
const vector<int> second = {42};
const vector<int> concatenation = first + second;
I know that vector doesn't have an addition operator like string, but that's the behavior that I want. Such that concatenation would contain: 13 and 42.
I know that I can initialize concatenation like this, but it prevents me from making concatenation const:
vector<int> concatenation = first;
first.insert(concatenation.end(), second.cbegin(), second.cend());
No, it's not possible if you require that
no helper function is defined, and
the resulting vector can be declared const.
template<typename T>
std::vector<T> operator+(const std::vector<T>& v1, const std::vector<T>& v2){
std::vector<T> vr(std::begin(v1), std::end(v1));
vr.insert(std::end(vr), std::begin(v2), std::end(v2));
return vr;
}
This does require a helper "function", but at least it allows you to use it as
const vector<int> concatenation = first + second;
I think you have to write a help function. I'd write it as:
std::vector<int> concatenate(const std::vector<int>& lhs, const std::vector<int>& rhs)
{
auto result = lhs;
std::copy( rhs.begin(), rhs.end(), std::back_inserter(result) );
return result;
}
The call it as:
const auto concatenation = concatenate(first, second);
If the vectors are likely to be very large (or contain elements that are expensive to copy), then you might need to do a reserve first to save reallocations:
std::vector<int> concatenate(const std::vector<int>& lhs, const std::vector<int>& rhs)
{
std::vector<int> result;
result.reserve( lhs.size() + rhs.size() );
std::copy( lhs.begin(), lhs.end(), std::back_inserter(result) );
std::copy( rhs.begin(), rhs.end(), std::back_inserter(result) );
return result;
}
(Personally, I would only bother if there was evidence it was a bottleneck).
class Vector : public vector<int>
{
public:
Vector operator+(const Vector& vec);
};
Vector Vector::operator+(const Vector& vec)
{
for (int i = 0; i < vec.size(); i++)
{
this->push_back(vec[i]);
}
return *this;
}
Let me preface this by saying this is a hack, and will not give an answer to how to do this using a vector. Instead we'll depend on sizeof(int) == sizeof(char32_t) and use a u32string to contain our data.
This answer makes it exceedingly clear that only primitives can be used in a basic_string, and that any primitive larger than 32-bits would require writing a custom char_traits, but for an int we can just use u32string.
The qualification for this can be validated by doing:
static_assert(sizeof(int) == sizeof(char32_t));
Once size equality has been established, and with the knowledge that things like non-const data, and emplace or emplace_back cannot be used, u32string can be used like a vector<int>, with the notable inclusion of an addition opperator:
const vector<int> first = {13};
const vector<int> second = {42};
const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());
[Live Example]
I came across this question looking for the same thing, and hoping there was an easier way than the one I came up with... seems like there isn't.
So, some iterator trickery should do it if you don't mind a helper template class:
#include <vector>
#include <iostream>
template<class T>
class concat
{
public:
using value_type = typename std::vector<T>::const_iterator::value_type;
using difference_type = typename std::vector<T>::const_iterator::difference_type;
using reference = typename std::vector<T>::const_iterator::reference;
using pointer = typename std::vector<T>::const_iterator::pointer;
using iterator_category = std::forward_iterator_tag;
concat(
const std::vector<T>& first,
const std::vector<T>& last,
const typename std::vector<T>::const_iterator& iterator) :
mFirst{first},
mLast{last},
mIterator{iterator}{}
bool operator!= ( const concat& i ) const
{
return mIterator != i.mIterator;
}
concat& operator++()
{
++mIterator;
if(mIterator==mFirst.end())
{
mIterator = mLast.begin();
}
return *this;
}
reference operator*() const
{
return *mIterator;
}
private:
const std::vector<T>& mFirst;
const std::vector<T>& mLast;
typename std::vector<T>::const_iterator mIterator;
};
int main()
{
const std::vector<int> first{0,1,2,3,4};
const std::vector<int> last{5,6,7,8,9};
const std::vector<int> concatenated(
concat<int>(first,last,first.begin()),
concat<int>(first,last,last.end()));
for(auto i: concatenated)
{
std::cout << i << std::endl;
}
return 0;
}
You may have to implement operator++(int) or operator== depending on how your STL implements the InputIterator constructor, this is the minimal iterator code example I could come up with for MingW GCC.
Have Fun! :)

STL sort question

I have vector of structures:
vector<Custom> myvec;
Custom is a structure:
struct Custom
{
double key[3];
};
How to sort myvec by key[0]. key[1] or key[2] using STL sort algorithm?
Write a custom comparator:
template <int i> struct CustomComp
{
bool operator()( const Custom& lhs, const Custom& rhs) const
{
return lhs.key[i]<rhs.key[i];
}
};
and then sort e.g. by using std::sort(myvec.begin(),myvec.end(),CustomComp<0>()); (this sorts by the first key entry)
Or with a more recent compiler (with c++0x lambda support):
std::sort(myvec.begin(), myvec.end(),
[]( const Custom& lhs, const Custom& rhs) {return lhs.key[0] < rhs.key[0];}
);
By using a a custom comparator.
struct CustomLess {
size_t idx;
CustomLess(size_t i) : idx(i) {}
bool operator()(Custom const& a, Custom const& b) const {
return a.key[idx] < b.key[idx];
}
};
then
std::sort(myvec.begin(), myvec.end(), CustomLess(1)); // for 1
Note: I did not use a template because, while using a template enables the compiler to optimize for that specific index, it prevents you from selecting the index at runtime, e.g. based on userinput, so it's less flexible/can't do as much as the nontemplated version. And as we all know, premature optimization is evil :)
I'm not sure why so many of the answers posted are focusing on functors. There is no need for a functor with the OP's stated requirement. Here are 2 non-functor solutions:
1: Overload operator< in the Custom class
bool Custom::operator< (const Custom& rhs)
{
return key[0] < rhs.key[0];
}
// can call sort(myvec.begin(), myvec.end());
2: Create a custom comparison function
template<int i> bool CustomLess(const Custom& lhs, const Custom& rhs)
{
return lhs.key[i] < rhs.key[i];
}
// can call sort(myvec.begin(), myvec.end(), CustomLess<0>);
bool CompareCustoms(const Custom& lhs, const Custom& rhs)
{
// Compare criteria here
return (lhs.key[0] < rhs.key[0]);
}
sort(myvec.begin(), myvec.end(), CompareCustoms);

How to use a lambda expression as a template parameter?

How to use lambda expression as a template parameter? E.g. as a comparison class initializing a std::set.
The following solution should work, as lambda expression merely creates an anonymous struct, which should be appropriate as a template parameter. However, a lot of errors are spawned.
Code example:
struct A {int x; int y;};
std::set <A, [](const A lhs, const A &rhs) ->bool {
return lhs.x < rhs.x;
} > SetOfA;
Error output (I am using g++ 4.5.1 compiler and --std=c++0x compilation flag):
error: ‘lhs’ cannot appear in a constant-expression
error: ‘.’ cannot appear in a constant-expression
error: ‘rhs’ cannot appear in a constant-expression
error: ‘.’ cannot appear in a constant-expression
At global scope:
error: template argument 2 is invalid
Is that the expected behavior or a bug in GCC?
EDIT
As someone pointed out, I'm using lambda expressions incorrectly as they return an instance of the anonymous struct they are referring to.
However, fixing that error does not solve the problem. I get lambda-expression in unevaluated context error for the following code:
struct A {int x; int y;};
typedef decltype ([](const A lhs, const A &rhs) ->bool {
return lhs.x < rhs.x;
}) Comp;
std::set <A, Comp > SetOfA;
The 2nd template parameter of std::set expects a type, not an expression, so it is just you are using it wrongly.
You could create the set like this:
auto comp = [](const A& lhs, const A& rhs) -> bool { return lhs.x < rhs.x; };
auto SetOfA = std::set <A, decltype(comp)> (comp);
For comparators used this way, you're still better off with a non-0x approach:
struct A { int x; int y; };
struct cmp_by_x {
bool operator()(A const &a, A const &b) {
return a.x < b.x;
}
};
std::set<A, cmp_by_x> set_of_a;
However, in 0x you can make cmp_by_x a local type (i.e. define it inside a function) when that is more convenient, which is forbidden by current C++.
Also, your comparison treats A(x=1, y=1) and A(x=1, y=2) as equivalent. If that's not desired, you need to include the other values that contribute to uniqueness:
struct cmp_by_x {
bool operator()(A const &a, A const &b) {
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
};
Not sure if this is what you're asking, but the signature of a lambda which returns RetType and accepts InType will be:
std::function<RetType(InType)>
(Make sure to #include <functional>)
You can shorten that by using a typedef, but I'm not sure you can use decltype to avoid figuring out the actual type (since lambdas apparently can't be used in that context.)
So your typedef should be:
typedef std::function<bool(const A &lhs, const A &rhs)> Comp
or
using Comp = std::function<bool(const A &lhs, const A &rhs)>;
the problem is the last template parameter is type not an object, so you might want to do the following
std::set <A, std::fuction<bool(const A &,const A &)>>
SetOfA([](const A lhs, const A &rhs) ->bool {
return lhs.x < rhs.x;
} > SetOfA;
to make it simpler you can do the following:
auto func = SetOfA([](const A lhs, const A &rhs) ->bool { return lhs.x < rhs.x;}
set <A,decltype(func)> SetOfA(func);
cheers