Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use lambda auto parameters in C++11

Tags:

c++

c++11

auto

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; });
like image 298
A. John Avatar asked May 06 '15 08:05

A. John


People also ask

What is the correct syntax for lambda expression in C++11?

Lambdas can both capture variables and accept input parameters. A parameter list (lambda declarator in the Standard syntax) is optional and in most aspects resembles the parameter list for a function. auto y = [] (int first, int second) { return first + second; };

What is auto lambda expression?

Immediately invoked lambda expression is a lambda expression which is immediately invoked as soon as it is defined. For example, #include<iostream> using namespace std; int main(){ int num1 = 1; int num2 = 2; // invoked as soon as it is defined auto sum = [] (int a, int b) { return a + b; } (num1, num2);

Can lambda take parameters?

The lambda expressions are easy and contain three parts like parameters (method arguments), arrow operator (->) and expressions (method body). The lambda expressions can be categorized into three types: no parameter lambda expressions, single parameter lambda expressions and multiple parameters lambda expressions.


3 Answers

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:

  1. 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; });
    
  2. 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());
    
like image 170
leemes Avatar answered Oct 21 '22 14:10

leemes


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.

like image 36
Nim Avatar answered Oct 21 '22 14:10

Nim


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.

like image 11
Rich L Avatar answered Oct 21 '22 15:10

Rich L