C++11 Lambda Functions inside member methods inherit scope - c++

I've written a function foreach that accepts a lambda function ala:
void foreach(void (*p)(pNode))
{ /* ... */ }
Which works as intended if I pass a lambda function from the main loop:
int a = 5;
env.N().foreach
(
[&](pNode n)->void
{
n->tps(a);
}
);
However, if I try to call the same function from within a member method, the lambda function "inherits" the scope of the member function and generates a compiler error. For example, if I try to include it inside the member method of class Object named method(), I get the following error:
error: no matching function for call to ‘IDSet<Node>::foreach(Object::method()::<lambda(pNode)>)’
note: candidate is: void IDSet<T>::foreach(void (*)(IDSet<T>::pT)) [with T = Node, IDSet<T>::pT = pNode]
I realize this is the compiler being safe, since I could include instance-specific variables inside the lambda function, in which case the lambda would need to be scoped, however I'm wondering if it's possible to make this lambda "static".
I've tried a reinterpret_cast, however that gives me this error:
error: invalid cast from type ‘Object::method()::<lambda(pNode)>’ to type ‘void (*)(pNode)’
Specifying static before [&](pNode ... doesn't seem like valid syntax either.
Desperately, I also tried changing [&] to [=], [], [a], none of which worked.
Does anyone know if there is a way to do accomplish my goal of creating a "static" lambda function, or at any sort of lambda function that will be accepted for that matter?
Thanks!
Answer:
With help from Cat Plus Plus, I was able to turn my incorrect code:
void foreach(void (*p)(pT))
{
for(pTiter i = _map.begin(); i != _map.end(); i++)
{
(*p)(i->second);
}
}
into fully functional code:
void foreach(std::function<void(pT)>(p))
{
for(pTiter i = _map.begin(); i != _map.end(); i++)
{
p(i->second);
}
}
that does what I was looking for perfectly.

Well, you can not use pointers.
void foreach(std::function<void(pNode)>);

Related

Is this defining a lambda function and assigning the function pointer to a value at the same time?

Still many C++ codes are so difficult for me to understand..
Below is a code snippet from dlib (http://dlib.net file : dlib/external/pybind11/include/pybind11/pybind11.h)
It's a member function definition of class cpp_function and I didn't try to understand the code(no time to do that..that's sad..). I can't understand the syntax in the line I put *** this line! comment at below. I understand the lambda function(unnamed function), so is it assigning a function pointer to rec->impl, the function taking function_call &call as argument and returning handle? So, it looks like defining a function and at the same time assigning the function pointer to a variable. Having asked it, it looks so now.. Please someone confirm this.
void initialize(Func &&f, Return (*)(Args...), const Extra&... extra) {
using namespace detail;
struct capture { remove_reference_t<Func> f; };
...
rec->impl = [](function_call &call) -> handle { // <=== *** this line!
cast_in args_converter;
/* Try to cast the function arguments into the C++ domain */
if (!args_converter.load_args(call))
return PYBIND11_TRY_NEXT_OVERLOAD;
/* Invoke call policy pre-call hook */
process_attributes<Extra...>::precall(call);
/* Get a pointer to the capture object */
auto data = (sizeof(capture) <= sizeof(call.func.data)
? &call.func.data : call.func.data[0]);
capture *cap = const_cast<capture *>(reinterpret_cast<const capture *>(data));
/* Override policy for rvalues -- usually to enforce rvp::move on an rvalue */
const auto policy = return_value_policy_override<Return>::policy(call.func.policy);
/* Function scope guard -- defaults to the compile-to-nothing `void_type` */
using Guard = extract_guard_t<Extra...>;
/* Perform the function call */
handle result = cast_out::cast(
std::move(args_converter).template call<Return, Guard>(cap->f), policy, call.parent);
/* Invoke call policy post-call hook */
process_attributes<Extra...>::postcall(call, result);
return result;
};
...
using FunctionType = Return (*)(Args...);
constexpr bool is_function_ptr =
std::is_convertible<Func, FunctionType>::value &&
sizeof(capture) == sizeof(void *);
if (is_function_ptr) {
rec->is_stateless = true;
rec->data[1] = const_cast<void *>(reinterpret_cast<const void *>(&typeid(FunctionType)));
}
}
rec->impl = [](function_call &call) -> handle
creates a lambda which takes one argument of type function_call and returns a handle, then assigns it to rec->impl.
As lambdas are basically unnamed structs, they also have unnamed types. Since rec->impl obviously exists already and is thus not templatized on the lambda type, the lambda gets converted to some other type during the assignment. (Note: there could however be a templatized and overloaded operator= here)
Typically such types which can take lambdas are either std::function or function pointers as stateless lambdas can be converted to function pointers.

std::bind: error: too few arguments to function call, single argument was not specified

I have the following code:
void MyClass::create_msg(MyTime timestamp) {
// do things here ...
}
and I tried to create a std::bind for the above function:
MyMsg MyClass::getResult(MyTime timestamp) {
// do things here ...
std::bind(create_msg(), timestamp);
// do things ...
}
But got the following error:
error: too few arguments to function call, single argument 'timestamp' was not specified
std::bind(create_msg(), timestamp);
~~~~~~~~~~ ^
MyClass.cpp:381:1: note: 'create_msg' declared here
void MyClass::create_msg(MyTime timestamp) {
^
1 error generated.
What did I do wrong in this case? Thanks!
By the way, same error if I do:
std::bind(&MyClass::create_msg(), this, timestamp);
There are three issues here.
First, the argument you're giving to std::bind as your function is currently create_msg(). This means "call create_msg, take whatever result it produces, and pass that in as the first argument to std::bind." That's not what you want - you instead meant "take create_msg and pass it as the first parameter to std::bind." Since create_msg is a member function, you'll need to get a pointer to it like this:
std::bind(&MyClass::create_msg, /* ... */)
That will address one issue, but there's another one that will then pop up. When you use std::bind with a member function pointer, you need to prove std::bind with an extra parameter corresponding to the receiver object to use when calling that member function. I believe that in your case you want the current object to be the receiver, which would look like this:
std::bind(&MyClass::create_msg, this, timestamp)
That should work properly.
However, one could argue that there's a third issue here - rather than using std::bind, why not just use a lambda expression?
[timestamp, this] { create_msg(timestamp); }

c# concurrent, overlapping callbacks

A short purely technical question:
If I have an uncertain amount of overlapping (time-wise) instances of the class below. Is it and how is it ensured, that the "this" in "call_back_when_done" belongs to the same "this" as it was in "Start"?
class MyClass{
int ident = -1;
bool ready = false;
void Start(string url){
ident = aStaticClass.DoSomethingAndForkThread(url, callback_when_done);
}
void call_back_when_done(){
ready = true;
}
}
e.g.:
for (int i=0; i < 3; i++)
new MyClass().Start(<aURL>);
Thank You
At first, you can bind the function to "this" like described here using currying : (How) is it possible to bind/rebind a method to work with a delegate of a different signature?
I would prefer a lambda function for your example case like described here : C# Lambdas and "this" variable scope
Lambda functions are bound to the scope of the "this" context where they are created. Members of your surrounding Class are automatically visible to the Lambda function. Using a Lambda function you'll get shorter code which can also better optimized by the compiler.
It is guaranteed.
When you pass callback_when_done to DoSomethingAndForkThread in Start, you are not only passing the raw function pointer (like you would in C++ with &MyClass::callback_when_done, but some kind of tuple consisting of the method to call and the object on which the method should be called (this).
If you like it more explicit you can also write a closure manually:
void Start(string url) {
var that = this; // that get's captured by the closure
ident = aStaticClass.DoSomethingAndForkThread(url, () => that.callback_when_done());
}

How to get a member function pointer in MSVC?

I'm not going to get into too much of the details on the Excel side of things, I essentially took code from this example:
C++ app automates Excel (CppAutomateExcel)
solution1.cpp
So I've tried this code in MSVC and it compiles:
class foo { public: virtual void bar(){} };
int main()
{
void (foo::*p)() = &foo::bar;
}
But similar code to capture the address of the move function in Excel does not work:
int main()
{
Excel::_ApplicationPtr spXlApp;
HRESULT hr = spXlApp.CreateInstance(__uuidof(Excel::Application));
Excel::WorkbooksPtr spXlBooks = spXlApp->Workbooks;
Excel::_WorkbookPtr spXlBook = spXlBooks->Add();
Excel::_WorksheetPtr spXlSheet = spXlBook->ActiveSheet;
HRESULT(Excel::_Worksheet::*pMove)(...) = &spXlSheet->Excel::_Worksheet::Move;
<... irrelevant code ...>
return 0;
}
This has the following compiler error:
error C2276: '&': illegal operation on bound member function expression
If I remove the &, it says I should add it back:
error C3867: 'Excel::_Worksheet::Move': non-standard syntax; use '&' to create a pointer to member
Any help on what to do here would be greatly appreciated.
You say in your question "but similar code..." and then you show code in which you do not do the same thing. Try using the same syntax for setting pMove as you used for setting p in your smaller example. Try something like &Excel::_Worksheet::Move; (without the "spXlSheet->").
If you can specify the specific instance of the object for which to call the function pointer at the time that you set the function pointer as you have there, I'm not aware of such a capability. After dropping spXlSheet-> from where you set the variable, use it instead where you want to call the function pointer.
You need to declare the method pointer like this instead:
// or whatever parameter type Move() actually uses...
void (Excel::_Worksheet::*pMove)(tagVARIANT, tagVARIANT) = &Excel::_Worksheet::Move;
Then, to actually call pMove(), you would have to do something like this:
Excel::_WorksheetPtr spXlSheet = ...;
(spXlSheet.Get()->*pMove)(...);

C++ boost function issue

I did something to break the functionality in my program, but I can't figure out what. I define a typedef in a class headerfile:
typedef boost::function<void(instr_ptr, std::vector<ResultBase*>) > GenFunction;
And inside that class I have two instances:
GenFunction Gen;
GenFunction Kill
I set them as follows:
void DataFlowSolver::SetGenFunction(GenFunction &func)
{
Gen = func;
}
void DataFlowSolver::SetKillFunction(GenFunction &func)
{
Kill = func;
}
I have another function in a seperate header file:
void GenLiveVar(const instr_ptr instr, std::vector<ResultBase*> &list);
I create an instance of the DataFlowSolver class, and attempt to assign into it as follows:
blockSolver.SetGenFunction(GenLiveVar);
However, the compiler complains:
CFG.cc:617: error: no matching function for call to
'DataFlowSolver::SetGenFunction(void (&)(instr_ptr,
std::vector >&))'
DataFlowSolver.h:21: note: candidates are: void
DataFlowSolver::SetGenFunction(GenFunction&)
But it lets me do this:
GenFunction fun = GenLiveVar;
blockSolver.SetGenFunction(fun);
Anyone have an idea what might be wrong? I know this worked before, but I'm not sure how I managed to break it...
You are passing the boost::function into Set*Function by non-const reference. That prevents temporaries from being used as arguments, and the conversion from a normal function to a boost::function creates a temporary value. You will need to use a const reference for your parameter type for the code to work correctly.