How to use lambda auto parameters in C++11
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 ofX
, which ispair<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 outstd::
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());
C++11: how to use lambda as type parameter, where it requires a functor type like std::less/std::greater?
There are multiple ways:
- Let the compiler deduce the type of lamabda by using
decltype(lambda)
. But one thing you need to keep in mind: Prior to C++20, lambda type does not have a default constructor. As of C++20, ONLY stateless lambda (lambda without captures) has a default constructor, while stateful lambda (i.e., lambda with captures) has no default constructor (This is clearly documented on cppreference.com). Why does the default constructor matter here? The answer is that if a default constructor exists, you don't have to pass a compare function (cmp) to the priority_queue constructor as long as you specified the lambda type as the template argument. Since the default constructor exists only for stateless lambda starting from C++20, you'd better explicitly pass a cmp argument to the constructor:
auto cmp = [](int x, int y){return x>y;};
priority_queue<int, vector<int>, decltype(cmp)> q(cmp);
- Use the
<functional>
header to explicitly specify the lambda type:
#include <functional>
...
priority_queue<int, vector<int>, function<bool(int, int)>> q(cmp);
- Use a function-obejct class. In this case, you only need to specify the function-object class as a template type argument, and you don't need to pass the cmp argument to the constructor, because your own defined function-object class has a default (synthesized) constructor.
struct Cmp {
bool operator()(int x, int y) {return x > y;}
};
priority_queue<int, vector<int>, Cmp> q;
- Use the library-defined function objects whenever possible.
priority_queue<int, vector<int>, std::greater<int>> q;
Access auto parameter's type within lambda
The type of value
is an lvalue-reference, you can't get the member type from it and have to remove the reference part, e.g
typename std::decay_t<decltype(value)>::value_type v;
PS: You also need to add typename
in advance (as @Vlad answered) for the dependent type name. See Where and why do I have to put the “template” and “typename” keywords?.
LIVE
How to make C++11 functions taking function<> parameters accept lambdas automatically
Finally figured out a generic wrapper function make_function
(in current c++11) for converting any lambda to its corresponding std::function
object with type deduction. Now instead of using ctor:
map(function<int (int)>( [](int x) -> int { return x;} ), {1,2,3});
which requires giving the same type information twice, the following succinct form works
map(make_function([](int x) -> int { return x;}),a); //now OK
Code is below:
#include <vector>
#include <functional>
using namespace std;
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> {
typedef function<ReturnType (Args...)> f_type;
};
template <typename L>
typename function_traits<L>::f_type make_function(L l){
return (typename function_traits<L>::f_type)(l);
}
template <typename A,typename B>
vector<B> map(std::function<B (A)> f, vector<A> arr) {
vector<B> res;
for (int i=0;i<arr.size();i++) res.push_back(f(arr[i]));
return res;
}
int main () {
vector<int> a = {1,2,3};
map(make_function([](int x) -> int { return x;}),a); //now OK
return 0;
}
--original answer--
To answer my own question after a couple of weeks' search (and getting chastised for using std::function<> as parameters), probably the best way I can find to have function<>-typed parameters accept lambda's (in c++11) is simply via explicit cast:
map((function<int (int)>) ([](int x) -> int { return x;} ), {1,2,3});
Or using ctor:
map(function<int (int)>( [](int x) -> int { return x;} ), {1,2,3});
For comparison, if you have a function taking std::string (e.g. void ff(string s) {...}
), it can take const char*
automatically. (ff("Hi")
would work). The automatic conversion from lambda to std::function<>
does not similarly work in c++11 (, which is unfortunate, IMO).
Hopefully, things will improve in c++14/1y when lambdas can be properly typed or better type-deduced.
C++11 lambda function - how to pass parameter
Show lambda with parameters are used? How to pass parameters to them?
It works exactly like with any other type of callable object:
#include <iostream>
int main()
{
auto l = [] (int i) { std::cout << "The answer is " << i; };
l(42);
}
Also notice, that you do not need to store a lambda in a variable in order to invoke it. The following is an alternative way to rewrite the above program:
#include <iostream>
int main()
{
[] (int i) { std::cout << "The answer is " << i; } (42);
// ^^^^
// Invoked immediately!
}
The type of a lambda function (the so-called "lambda closure") is defined by the compiler, and is a functor with a call operator whose signature is the one you specify when defining the lambda. Therefore, you call a lambda exactly as you would call a functor (i.e. exactly as you would call a function - or any callable object).
Thus, if you want to assign a lambda to an object, the best practice is to let the compiler deduce its type by using auto
. If you do not want or cannot use auto
, then you may:
Use function pointers for non-capturing lambdas (capturing lambdas are not convertible to function pointers). In the above case, thus, the following will also work:
#include <iostream>
int main()
{
void (*f)(int) = [] (int i) { std::cout << "The answer is " << i; };
f(42);
}Use
std::function
(this is always possible, even if the lambda is capturing):#include <iostream>
#include <functional>
int main()
{
std::function<void(int)> f = [] (int i)
{ std::cout << "The answer is " << i; };
f(42);
}
Auto parameter type in lambda causes Use 'template' keyword to treat... error
Now that you have a template type (in the form of auto
) instead of a concrete type TestClass
, the get
function is dependent, and therefore you need to qualify it with the template
keyword:
tc.template get<int>();
Use a lambda as a parameter for a C++ function
You have 2 ways: make your function template:
template <typename F>
void myFunction(F&& lambda)
{
//some things
}
or erase type (with std::function
for example):
void
myFunction(const std::function<void()/*type of your lamdba::operator()*/>& f)
{
//some things
}
How to constrain an auto lambda parameter to a pointer to member function?
You can declare it as:
auto l = [](auto S::*pmf)
It does tie the pointer to a S
type, but it makes sense because it is that way you will use it.
Parameter list in Lambda
Lambda creation
I think I had the same confusion when I first saw lambdas.
So let's see what this expression means:
[](auto x, auto y) {return(y < x); }
This just creates the lambda object. It does not call the labda. Think of it as a class definition + object creation.
Your questions
Let's consider the declaration of sort
:
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );
and your call to it
sort(ivec.begin(), ivec.end(), [](auto x, auto y) { return(y < x); });
when the above line of code is being executed?
I'll interpret this as "when is the body of the lambda executed?"
Whenever sort
calls it. What you need to understand: sort
receives a parameter named comp
that is callable. This parameter can be of type: pointer to function or a callable type (i.e. a type with operator()
defined). A lambda is a special case of a callable type. When you call sort
you just pass this object to the sort
function. Now sort
has an object (comp
) that it can call whenever it wants/needs.
what is being passed in the parameter list as parameter?
Whatever sort
passes as arguments when it calls comp
. It the case of std::sort
it will call it with pairs of elements from the range with the purpose of determining if those two elements are already sorted between them or not.
Example
The easiest is to just see it in action. For this lets consider the simplest sorting algorithm: a dumb bubble sort:
template< class RandomIt, class Compare >
void bubble_sort( RandomIt first, RandomIt last, Compare comp )
{
for (auto left = first; left != last; ++left)
{
for (auto right = std::next(left); right != last; ++right)
{
if (!comp(*left, *right))
{
std::swap(*left, *right);
}
}
}
}
the algorithm is for exposition only
As you can see bubble_sort
makes calls to comp
by passing arguments. Like std::sort
the arguments passed are pairs of elements from the [first, last)
range.
Related Topics
Using Continue in a Switch Statement
How to Detect Possible/Potential Stack Overflow Problems in a C/C++ Program
Implementing the Derivative in C/C++
How to Get a List of Files in a Folder in Which the Files Are Sorted with Modified Date Time
Switch-Case Statement Without Break
What Is Void* and to What Variables/Objects It Can Point To
Meaningful Stack Traces for Address Sanitizer in Gcc
What Is the Use of "Delete This"
Interfaces VS Templates for Dependency Injection in C++
C++ Nested Classes Accessibility
How to Pan Images in Qgraphicsview
C++ Frontend Only Compiler (Convert C++ to C)
Alternative to C++ Static Virtual Methods
Print MACro Values Without Knowing the Amount of MACros
What Is Allowed in a Constexpr Function
Weird Undefined Symbols of Static Constants Inside a Struct/Class