Looks like if lambda is defined inside a member function and this is captured then inside lambda all class members can be accesses without using this keyword, that is I can do
some_class_field = ....
instead of
this->some_class_field = ....
Is it portable behavior or specific to Visual Studio?
Thanks.
It is expected :
§ 5.1.2 paragraph 7
The lambda-expression’s compound-statement yields the function-body (8.4) of the function call operator,
but for purposes of name lookup (3.4), determining the type and value of this (9.3.2) and transforming idexpressions
referring to non-static class members into class member access expressions using (*this) (9.3.1),
the compound-statement is considered in the context of the lambda-expression. [ Example:
struct S1 {
int x, y;
int operator()(int);
void f() {
[=]()->int {
return operator()(this->x + y); // equivalent to S1::operator()(this->x + (*this).y)
// this has type S1*
};
}
};
Related
I have not much experience in using lambda's - I was hoping someone could explain what I did below in 'layman's terms' (if possible).
I have a std::vector with a number of objects (or none). Each object has an id. I want to place the object with the id I am interested in at the back of the vector.
I did that like so
std::vector<my_ob> l_obs;
[...] // populate the vector
auto l_elem = std::find_if(l_obs.rbegin(),
l_obs.rend(), [](my_ob const& ob){ return ob.mv_id == 8;});
if(l_elem-l_obs.rbegin())
std::iter_swap(l_elem, l_obs.rbegin());
I am using a reverse iterator as I expect the match to already be at the back of the vector in most cases.
The above worked fine, until I moved it into a method and instead of trying to find '8', I wanted to find a value passed as a const int parameter. The compiler told me that the parameter I used was not captured, and that the lambda had no capture default. So I changed the lambda to
[=](my_ob const& ob){ return ob.mv_id == _arg;}
and this all seems to work now.
Why was this = sign needed?
Lambda expressions produce closure objects, which are function objects (similar to a struct with an overloaded operator()).
In order for closures to use variables in the outer scope, they must know how: either by copying the variable into the closure itself, or by referring to it.
Writing
[=](my_ob const& ob){ return ob.mv_id == _arg;}
is equivalent to
[_arg](my_ob const& ob){ return ob.mv_id == _arg;}
which roughly desugars to
struct LAMBDA
{
int _arg;
LAMBDA(int arg) : _arg{arg} { }
auto operator()(my_ob const& ob) const { return ob.mv_id == _arg; }
};
As you can see, _arg needs to be available in the scope of the generated LAMBDA function object, so it needs to be a data member of the closure.
When you were using a literal, no captures were needed as the generated closure looked like:
struct LAMBDA
{
auto operator()(my_ob const& ob) const { return ob.mv_id == 5; }
};
Basically, I am looking for something more or less equivalent to the following C code:
int theGlobalCount = 0;
int
theGlobalCount_get() { return theGlobalCount; }
void
theGlobalCount_set(int n) { theGlobalCount = n; return; }
You could use a neat trick: declare a mutable global variable, and make a ref (aka mutable reference) point to it (no GC is required to make this work!). Then, implement functions to provide access to the mutable reference.
local
var theGlobalCount_var : int = 0
val theGlobalCount = ref_make_viewptr (view# theGlobalCount_var | addr# theGlobalCount_var)
in // in of [local]
fun
theGlobalCount_get () : int = ref_get_elt (theGlobalCount)
fun
theGlobalCount_set (n: int): void = ref_set_elt (theGlobalCount, n)
end // end of [local]
Note that declarations inside local-in are visible only to code inside in-end. Therefore, neither theGlobalCount_var nor theGlobalCount are visible outside the scope of the local.
Full code: glot.io
You can also use the extvar feature to update an external global variable (declared in the target language). This is very useful if you compile ATS to a language that does not support explicit pointers (e.g., JavaScript). Here is a running example that makes use of this feature:
http://www.ats-lang.org/SERVER/MYCODE/Patsoptaas_serve.php?mycode_url=http://pastebin.com/raw/MsXhVE0A
We have the following lightweight classes:
struct A {};
struct B { A get_a() const { return /* sth */; } };
And let's suppose I have an ordered container of type A, and I want to copy objects from another container of type B to it:
std::copy(b_cont.begin(), b_cont.end(),
std::make_insert_iterator(a_cont, a_cont.end())
);
Of course, it won't work because a_cont and b_cont have different types, and classes A and B don't provide conversion operators. The most obvious solution is to call the function get_a for each B object on the range [b_cont.begin(), b_cont.end()), so, lets write a custom insert iterator:
template<template<class...> class container>
struct ba_insert_iterator : public std::insert_iterator<container<A> >
{
using std::insert_iterator<container<A>>::insert_iterator;
ba_insert_iterator& operator=(B const& o)
{
std::insert_iterator<container<A>>::operator=(o.get_a());
return *this;
}
};
template<template<class...> class container>
ba_insert_iterator<container> make_a_inserter(container<A>& c)
{ return ba_insert_iterator<container>(c, c.end()); }
Just an iterator that receives an object of type B, instead of another one of type A, and a function to create them easily. But when instantiating the template:
std::copy(b_cont.begin(), b_cont.end(), make_a_inserter(a_cont));
It says that it doesn't find the operator= because the second operand is an A object (as expected), but the first operand is an std::insert_iterator<std::set<A> >!!, so the compiler is "casting" the iterator to its clase base, which of course lacks of a method for receiving B objects to insert.
Why does it happen?
You inherited operator* (and operator++ too, for that matter) from insert_iterator.
And those return insert_iterator&, not ba_insert_iterator&.
For obvious reasons, std::copy dereferences the output iterator before assigning to it.
struct pair{
int first;
int second;
}
vector<pair> v;
sort(v.begin(), v.end(), [](pair p1, pair p2){return p1.first < p2.first});
what does the [](pair p1, pair p2){return p1.first < p2.first} mean in sort? function pointer or anything else? I can't figure out the keywords to search.
That's a Lambda Expression and the subscript operator is what introduces it. Lambda expressions were introduced in C++11.
I couldn't put it better than the MSDN article linked above which defines a lambda expression as follows:
is a convenient way of defining an anonymous function object right at the location where it is invoked or passed as an argument to a function.
this is a lambda expresion. See example below:
void abssort(float* x, unsigned n) {
std::sort(x, x + n,
// Lambda expression begins
[](float a, float b) {
return (std::abs(a) < std::abs(b));
} // end of lambda expression
);
}
reference: https://msdn.microsoft.com/en-us/library/dd293608.aspx
the function that is being passed as a parameter does not have a "function name" - it is anonymous. This is a useful abstraction as all that is needed is the functionality that is being passed (the name does not matter).
Google's v8 documentation describes how to add a global function to a JavaScript context. We can implement a printf-like function quite easily using the new lambda feature from C++11:
Handle<ObjectTemplate> global = ObjectTemplate::New();
global->Set(String::New("print"), FunctionTemplate::New(
[](const v8::Arguments &args) -> v8::Handle<v8::Value>
{
v8::String::AsciiValue ascii(args[0]);
std::cout << *ascii << "\n";
} ));
Persistent<Context> context = Context::New(NULL, global);
This works well for any global JavaScript function that is either stateless or references a global C++ variable (i.e. std::cout). But what if we want our global JavaScript function to reference a non-global C++ variable? For example, suppose we are creating several different JavaScript contexts each with its own global print function that uses a different C++ std::ostream? If v8 function templates used std::function objects instead of function pointers, the we would do something like this:
Persistent<Context> create_context(std::ostream &out)
{
Handle<ObjectTemplate> global = ObjectTemplate::New();
global->Set(String::New("print"), FunctionTemplate::New(
[&out](const v8::Arguments &args) -> v8::Handle<v8::Value>
{
v8::String::AsciiValue ascii(args[0]);
out << *ascii << "\n";
} ));
return Context::New(NULL, global);
}
Unfortunately, v8 does not seem to support this. I assume (hope?) that v8 has a way of doing something functionally equivalent, but I find myself mystified by the Doxygen for v8::FunctionTemplate. Would anyone who has attempted something similar be willing to distill the process down into something more understandable? I would also like to learn how to create a global instance of a JavaScript object that is bound to an existing, non-global instance of a C++ object.
In answer to my own question... the key is to realize that v8::Arguments is not simply an array of arguments. It also contains the exceedingly useful Callee() and Data() methods. If the function is a method of a JavaScript object then Callee() can, I think, be used to get ahold of whatever instance of that object the method was called on. Useful state information could then be stored in the object instance. You can also supply a data handle, which may point to any C++ object through void*, when adding a function template to an object. This function-specific data handle may then be accessed through the Data() method.
Below is a reasonably complete example of what I was trying to do in the question using v8::Arguments::Data(). Hopefully this will be useful to anyone who wants to do something similar. If you have an alternative strategy you like (and I am certain there is more than one way of doing this), please feel free to add it in another answer!
#include <iostream>
#include <ostream>
#include <v8.h>
// add print() function to an object template
void add_print(v8::Handle<v8::ObjectTemplate>& ot, std::ostream* out)
{
// add function template to ot
ot->Set(v8::String::New("print"), v8::FunctionTemplate::New(
// parameter 1 is the function callback (implemented here as a lambda)
[](const v8::Arguments& args)->v8::Handle<v8::Value>
{
// recover our pointer to an std::ostream from the
// function template's data handle
v8::Handle<v8::External> data = v8::Handle<v8::External>::Cast(args.Data());
std::ostream* out = static_cast<std::ostream*>(data->Value());
// verify that we have the correct number of function arguments
if ( args.Length() != 1 )
return v8::ThrowException(v8::String::New("Too many arguments to print()."));
// print the ascii representation of the argument to the output stream
v8::String::AsciiValue ascii(args[0]);
*out << *ascii << "\n";
// like 'return void;' only in JavaScript
return v8::Undefined();
},
// parameter 2 is the data handle with the pointer to an std::ostream
v8::External::New(out)
));
}
int main()
{
// create a stack-allocated handle scope
v8::HandleScope handle_scope;
// create a global template
v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
// add a print() function using std::cout to the global template
add_print(global, &std::cout);
// create a context
v8::Persistent<v8::Context> context = v8::Context::New(nullptr, global);
// enter the created context
v8::Context::Scope context_scope(context);
// create a string containing the JavaScript source code
v8::Local<v8::String> source = v8::String::New("print('1 + 1 = ' + (1 + 1));");
// compile the source code
v8::Local<v8::Script> script = v8::Script::Compile(source);
// run the script
script->Run();
// dispose of the persistent context
context.Dispose();
return 0;
}