Why mutable lambda with pointer to member function? - c++

I'd like to get my mucky paws on the operator() of a lambda function. The following seems up the task:
template <typename F>
void bar(F func) {
void (F ::*pm)();
pm = &F::operator();
}
However, in the following, I need to include the mutable keyword. Why is that? Is it possible to above instead declare a pointer to member function, which can target arbitrary lambdas?
int main(int argc, char *argv[])
{
bar([]() mutable {});
return 0;
}

According to 5.1.2 of the N3291 C++0x specification, the lambda's operator() is const unless you explicitly declare it mutable:
This function call operator is declared const (9.3.1) if and only if the lambda-
expression’s parameter-declaration-clause is not followed by mutable.
You may be able to do some template metaprogramming magic to detect which is which.
However, it should be noted that, once func goes out of scope, you can't use that member pointer anymore. And it is a member pointer, not a function pointer, so you can't convert between the two.

C++0x lambdas are const by default, unlike the rest of the language. Consequently, your member-function variable must be const as well. The following should work:
template<typename F>
void bar(F func) {
typedef void (F::*pm_t)() const;
pm_t pm = &F::operator();
}

Consider this:
int x=0;
auto show = [x]() mutable
{
x++;
};
show();
The variable 'x' is being captured by-value, and without mutable, you cannot modify the local copy of this variable. Specify mutable to enable modification of this local copy. For by-value captures, it doesn't matter if value is modified, the original x variable won't be modified.

Related

How can I use decltype on a variable in a lambda without capturing it?

I'm trying to design a C++ macro that needs to look something like this:
#define MY_MACRO(OBJECT, METHOD) \
[](BaseClass* obj) \
{ \
return static_cast<decltype(OBJECT)>(obj)->METHOD();\
}
Basically, a macro that translates into a lambda that calls a given method on a given object. But the lambda needs to take a base class of the object as a parameter (My use case guarantees that the cast will always work). Furthermore, the method to be called might not be on the base class.
The usage for this macro is that I have another method which I cannot modify declared as:
void Foo(std::function<int(BaseClass*)>);
and I need to be able to call it using my macro as a parameter like so:
T x;
Foo(MY_MACRO(x, method)); // match std::function<int(T*)>
However, the macro code doesn't work because I'm not capturing OBJECT, so it's not in scope when I need to pass it to decltype. Conceptually though, all the information the compiler needs is there... How can I do this? Is it possible?
A few constraints:
The lambda's parameter needs to be BaseClass. I can't make it decltype(OBJECT).
My situation does not allow me to capture OBJECT.
I don't have access to the C++14 feature of generalized lambda captures.
I need access to the type of the object without capturing it.
You can do it directly. You are required to capture only when you odr-use the named entity, and unevaluated operands, like those of decltype, don't odr-use anything. This is perfectly fine:
void f(){
int x;
[]{ decltype(x) y = 0; };
}
You can add an optional parameter to the lambda with the type that you want, and use decltype on that parameter. Here's an example of the pattern, minus the macro:
int main() {
int foo = 4;
auto lambda = [](double* bar, decltype(foo)* TP = nullptr) {
return static_cast<std::remove_pointer<decltype(TP)>::type>(*bar);
};
double x = 5;
return lambda(&x);
}
I get a pointer to decltype(foo) here because pointer types can easily be defaulted to nullptr to ensure that the parameter is optional. If decltype(foo) already resolves to a pointer type, as in your case if I got it right, you wouldn't need it (and the remove_pointer).
Here's an attempt:
template <typename T>
auto lambda_maker(int (T::* MF)())
{
return [](T* p) -> int { return (p->*MF)(); };
}
#define MY_MACRO(OBJ, METH) lambda_maker<decltype(OBJ)>(METH)

Passing lambda functions to other methods

Do lambda function have a signature so that I can pass them around?
template<class Fn>
HRESULT foreach(Fn _fuction)
{
}
object->foreach(
[param1, param2] (int item)
{
}
);
object->foreach(
[param1, param2, param3] (int item)
{
}
);
I want to use a typedef function instead of templates, I think the type of the function will strict the formal parameters but will allow captured list to vary.
can I use typedef instead of templates to pass lambda functions around?
something like:
typedef void (*Fn)(int);
but allows lambda not function pointer.
I tried using std::fuction but seems not working.
The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non-
union class type — called the closure type ...
(C++11 §5.1.2/3, emphasis mine)
My reading of this is that even if two lambda-expressions have the same parameter list, return type, and capture list, they nevertheless have different types.
auto f = []{};
typedef decltype(f) lambda_type;
void g(lambda_type lambda) { lambda(); }
int main() {
g(f); // OK
g([]{}); // error: type mismatch
}
So no, what you are trying to do cannot be done. As others have suggested, try using std::function, or retain the template (what's wrong with templates, anyway?)
The actual type of a lambda is unspecified. But they are convertible to function; in your case, std::function<void(int)> (void is the return type, the parameter types go in the parentheses).

Is there a way to shorten the C++11 lambda signature in declaration?

I want to shorten the following type of lambdas:
[] (SomeVeryLongTemplateType<int, float, char, std::string>, AnotherLongType) {};
Since the only reason for this lambda is to initialize some class std::function<...> member - it doesn't capture anything, it doesn't have argument names, it returns nothing, it does nothing.
If the shortening operation is expressed as a function of the number of arguments in signature, then I want this function to have the complexity O(1).
Is there a way to do that?
Looks like you're looking for an empty lambda which does nothing, so that your std::function object will always be in callable state!
If so, then use this one which can be reused, for any number of parameters:
static const struct empty_lambda_t //static and const applies to the object!
{
template<typename ...T>
void operator()(T && ... ) const {} //does nothing
}empty_lambda {}; //declare an object which is static and const
And then use it as:
std::function<void()> fun1 = empty_lambda;
std::function<void(int,int)> fun2 = empty_lambda;
std::function<void(whatever)> fun3 = empty_lambda;
Hope that helps.
in C++14 there will be "generic lambdas" that should simplify long type names in parameters as I understand:
auto lambda = [](auto x, auto y) {return x + y; };
here auto is like Template type
http://en.wikipedia.org/wiki/C%2B%2B14#Generic_lambdas
You're looking for "polymorphic lambdas". They do not exist (yet), so no.
However, you can make it easier with proper use of typedefs, so you don't have to type the entire thing every single time.

Should all lambda declarations be const static?

Lambda object declarations (std::function<>() / auto lambda = []()...) are always literals, right? So does that mean we should, for clarity, coding etiquette and even performance, always declare them const static just like any other scoped literal constant?
Lambda object declarations (std::function<>() / auto lambda = ...) are always literals, right?
No, lambdas are not literals. They can capture state from the enclosing scope and that can be non-const. Consider:
int f(int a, int b) {
auto lambda = [=](int x) { return a*x; };
return lambda(b);
}
If you add static there, the variable lambda will be shared by all the code that uses f, and it will only be initialized on the first call capturing the value of a from the first call to f. By not having it static each call to f will use it's own first argument.
While the example is very artificial, I hope it helps to clear the point.

Const keyword appended to the end of a function definition... what does it do?

Suppose I define a function in C++ as follows:
void foo(int &x) const {
x = x+10;
}
And suppose I call it as follows:
int x = 5;
foo(x);
Now typically (without the const keyword), this would successfully change the value of x from the caller's perspective since the variable is passed by reference. Does the const keyword change this? (i.e. From the caller's perspective, is the value of x now 15?)
I guess I'm confused as to what the const keyword does when it is appended to the end of a function definition... any help is appreciated.
This won't work. You can only const-qualify a member function, not an ordinary nonmember function.
For a member function, it means that the implicit this parameter is const-qualified, so you can't call any non-const-qualified member functions or modify any non-mutable data members of the class instance on which the member function was called.