C++ - binding function - c++

I have some (library API, so I can't change the function prototype) function which is written the following way:
void FreeContext(Context c);
Now, at some moment of my execution I have Context* local_context; variable and this is also not a subject to change.
I wish to use boost::bind with FreeContext function, but I need to retrieve Context from local variable Context*.
If I write my code the following way, the compiler says it's "illegal indirection":
boost::bind(::FreeContext, *_1);
I managed to solve this problem the following way:
template <typename T> T retranslate_parameter(T* t) {
return *t;
}
boost::bind(::FreeContext,
boost::bind(retranslate_parameter<Context>, _1));
But this solution doesn't seem really good to me. Any ideas on how to solve this using something like *_1. Maybe writing a small lambda function?

You could use Boost.Lambda which have overloaded the * operator for _n.
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <algorithm>
#include <cstdio>
typedef int Context;
void FreeContext(Context c) {
printf("%d\n", c);
}
int main() {
using boost::lambda::bind;
using boost::lambda::_1;
Context x = 5;
Context y = 6;
Context* p[] = {&x, &y};
std::for_each(p, p+2, bind(FreeContext, *_1));
return 0;
}

Use either Boost.Lambda or Boost.Phoenix to have a working operator* on a placeholder.

You can also place the Context pointer in a shared_ptr with a custom deleter:
#include <memory> // shared_ptr
typedef int Context;
void FreeContext(Context c)
{
printf("%d\n", c);
}
int main()
{
Context x = 5;
Context* local_context = &x;
std::shared_ptr<Context> context(local_context,
[](Context* c) { FreeContext(*c); });
}
Not sure this is relevant though. Good luck!

Related

Does constructing a struct with default move constructor and wrap it in a shared_ptr is safe to pass to a lambda function executed in a tbb::task?

Context: On one of my C++11 application, object serialization and publish of message is time consuming. Therefore I want to do it in a separate thread using Intel TBB library (more specifically using a tbb::task_group)
Issue: the object to serialize is a struct where some of the properties are std::vector<std::unique_ptr<SomeObject>>, making it impossible to pass by copy to the lambda executed in a task
Approximately it look like
struct MockedDC {
MockedDC(int x, std::vector<std::unique_ptr<SomeObject>> v) : x(x),
v(std::move(v)) {};
int x;
std::vector<std::unique_ptr<SomeObject>> v;
};
The "solution" I found, is to reconstruct on the heap with the move-constructor my instance and wrap it in a shared_ptr<MockedDC> which is copyable. In the end the function which invoke the tbb::task_group::run look like
// function called like this `executeInThread(taskGroup, std::move(mockedDC))`
void executeInThread(tbb::task_group& taskGroup, MockedDC mockedDC) {
const std::shared_ptr<MockedDC> sharedMockedDC(new MockedDC(std::move(mockedDC)));
auto f = [sharedMockedDC] {
const auto serialized(serializer(*sharedMockedDC)); // pass by reference
publish(serialized);
};
taskGroup.run(f);
};
it compile and run fine, but I can't put it under pressure as it will be in real life condition
so my question is is it safe/sane to do this ?
I found on another stackoverflow question an alternative, but the implementation looks difficult to maintain given my C++ knowledge :) that's why I want to stick with the shared_ptr approach as suggested somewhere else
What I tried so far: I wrote a dummy code to test the thing, but I think its not enough to validate this approach. I also wanted to compile with some sanitization flags, but tbb fail to link with a bunch of errors like undefined reference to __ubsan_handle_pointer_overflow
Here is the dummy example if that help to answer (it compile and run without issues (except some int overflow but that not an issue I guess))
#include <cstdio>
#include <iostream>
#include <memory>
#include <vector>
#include <numeric>
#include "tbb/task_scheduler_init.h"
#include "tbb/task_group.h"
struct MockedDC {
MockedDC(int seed, size_t baseLen) : seed(seed), baseLen(baseLen) {
this->a_MDC.reserve(baseLen);
for (size_t i = 0; i < baseLen; ++i)
this->a_MDC.emplace_back(new int((seed + i) / (seed + 1)));
};
int seed;
size_t baseLen;
std::vector<std::unique_ptr<int>> a_MDC;
};
void executeInThread(tbb::task_group& taskGroup, MockedDC mockedDC) {
const std::shared_ptr<MockedDC> sharedMockedDC(new MockedDC(std::move(mockedDC)));
auto f = [sharedMockedDC] {
std::cout <<
std::accumulate(sharedMockedDC->a_MDC.begin(), sharedMockedDC->a_MDC.end(), 0, [](int acc, const std::unique_ptr<int>& rhs) {
return acc + *rhs;
})
<< std::endl << std::flush;
};
taskGroup.run(f);
};
void triggerTest(tbb::task_group& taskGroup) {
for (size_t i = 0; i < 1000000; ++i) {
MockedDC mdc(i, 10000000);
executeInThread(taskGroup, std::move(mdc));
}
return ;
};
int main() {
tbb::task_scheduler_init tbbInit(tbb::task_scheduler_init::automatic);
//tbb::task_scheduler_init tbbInit(8);
tbb::task_group taskGroup;
triggerTest(taskGroup);
taskGroup.wait();
return (0);
};
PS: using C++14 new capture by move doesn't work because of TBB library :/

Why don't lambda expressions require <functional>, but function<void()> does?

I have some code use lambda expression like it:
#include <vector>
#include <algorithm>
int main(){
std::vector<int> vi={3,1};
std::sort(vi.begin(),vi.end(),[](int x,int y){
return x<y;
});
return 0;
}
Which doesn't require #include< functional> to compile, but if I use a variable to store the lambda function:
#include <vector>
#include <algorithm>
#include <functional>
int main(){
std::vector<int> vi={3,1};
std::function<void()> compf=[](int x,int y){
return x<y;
};
std::sort(vi.begin(),vi.end(),compf);
return 0;
}
Then I need to include <functional> to compile, why? And why sort() doesn't also include <functional> already?
Because a lambda expression is a core language feature, provided by the compiler. std::function is a library feature, implemented in code. Note that you don't need to include anything to store the lambda in a variable.
auto f = [](int x, int y){ return x < y; };
You only need to include <functional> if you plan to store it in a std::function (because that's where it's implemented).
You seem to be under the impression that the type of a lambda is a std::function. It is not. Every lambda expression has its own unique, unnameable type. I captured that type above, with auto. std::function is a more general type that can store any function-like object with the appropriate signature. For example, I can create a std::function<int(int,int)> object, and assign to it a normal function, a function object, and a lambda.
#include <functional>
int minus_func(int a, int b) { return a - b; }
struct plus_t {
int operator()(int a, int b) const { return a + b; }
};
int main() {
auto mult_lambda = [](int a, int b) { return a * b; };
std::function<int(int,int)> func;
func = minus_func;
func = plus_t{};
func = mult_lambda;
}
There's also a cost to that generality, in the form of dynamic allocation, and indirection. Whereas using a lambda through a variable of its actual type is very often inlined.
lambda functions are part of the language -- independent of any libraries.
std::function, on the other hand, is part of the standard library and is defined in the standard library header file functional.
Hence, use of
std::sort(vi.begin(),vi.end(),[](int x,int y){
return x<y;
});
does not require functional to be #included while use of
std::function<void()> compf=[](int x,int y){
return x<y;
};
std::sort(vi.begin(),vi.end(),compf);
requires functional to be #included.

C++ Creating a function that is being pointed to as an argument

So this is confusing to explain, but I will try my best.
I have a function one of my classes that takes a function pointer as an argument, and what I would like to do is define the function as part of the argument. ie:
object->setFunctionPointer({string a = ""; return a;});
Is this possible? if so, what is the proper syntax of this?
In C++11, you can do it. You can use C++ lambda (anonymous functions).
See the sample code at http://ideone.com/8ZTWSU
#include <iostream>
using namespace std;
typedef const char * (*funcptr)();
funcptr s;
void setFuncPtr(funcptr t)
{
s = t;
}
int main() {
// your code goes here
setFuncPtr([]{return "Hello \n"; });
printf("%s\n", s());
return 0;
}
If we are talking about C++ you should use std::function and not function pointers. Unless you are interfacing with C APIs.
class Foo{
SetFunc(std::function<void(int)> func)
{
m_func = func;
}
private:
std::function<void(int)> m_func;
};
If your function is a member of a class, you cannot take an ordinary function pointer to store its address. What you need is a delegate; which are specialised function pointers for methods. Search the internet for C++ delegate and you should find numerous examples.
(Note: maybe there is an exception for static methods; I don't remember.)
Here is a complete example. Since c++11 this is the way to go:
#include<functional>
#include<string>
#include<iostream>
using namespace std;
class Object
{
public:
void setFunctionPointer(function<string(void)> function)
{
m_function = function;
}
string run()
{
return m_function();
}
private:
function<string(void)> m_function;
};
int main(int argc, char**argv)
{
Object *object = new Object;
object->setFunctionPointer([]{string a = "FOO"; return a;}); // here is the function assignment
cout << object->run() << endl;
delete object;
}
When run this prints FOO to stdout.

Problems adapting member functions in Phoenix

I use BOOST_PHOENIX_ADAPT_FUNCTION all the time in Spirit. I'd like to be able to adapt member functions for all of the same reason. However, I get compile errors if I do something like this:
struct A { int foo(int i) { return 5*i; }};
BOOST_PHOENIX_ADAPT_FUNCTION(int, AFoo, &A::foo, 2)
Is there an easy way to adapt a member function? Note that I can't just store a bind expression in an auto because I am on VC2008. How come it doesn't just work like in bind and function?
Thanks,
Mike
The BOOST_PHOENIX_ADAPT_FUNCTION(RETURN,LAZY_NAME,FUNC,N)is really simple. It just creates a functor with a templated operator() that returns RETURN and has N template parameters. In its body it simply invokes FUNC(PARAMETERS...). But &A::foo is not directly callable, and so your error occurs. You can use:
BOOST_PHOENIX_ADAPT_FUNCTION(int,AFoo,boost::mem_fn(&A::foo),2)
Running on Coliru
#include <iostream>
#include <boost/phoenix.hpp>
#include <boost/phoenix/function.hpp>
#include <boost/mem_fn.hpp>
struct A {
A(int f) : f_(f) {}
int foo(int i) {
return f_*i;
}
private:
int f_;
};
BOOST_PHOENIX_ADAPT_FUNCTION(int,AFoo,boost::mem_fn(&A::foo),2)
int main() {
using namespace boost::phoenix;
using namespace boost::phoenix::arg_names;
A instance(5);
std::cout << AFoo(arg1,arg2)(&instance, 2) << std::endl;
}
Starting with the simplest:
How come it doesn't just work like in bind and function?
Because the macro is designed for functions, not member functions. Pointer-to-member-functions are very different from function pointers, so that's the end of the road.
In your example, A::foo doesn't actually need to be an instance method (non-static member function), so just add static (and an implicit parameter) and be done:
struct A {
static int foo(int i) {
return 5*i;
}
};
BOOST_PHOENIX_ADAPT_FUNCTION(int, AFoo, A::foo, 1)
Let's assume, though, that you did want to have the non-static member function. For this reason, let's add a little state to the A type:
struct A {
A(int f) : f_(f) {}
int foo(int i) { return f_*i; }
private:
int f_;
};
Phoenix provides the following approaches to create lazy actors calling member functions:
use the ->* operator. This leads to slightly obscure syntax:
A instance(9);
int direct = (arg1->*&A::foo)(arg2)
(&instance, 7); // direct == 63
alternatively, you can use a bind expression (note: boost::phoenix::bind here!), which might just be what you were looking for:
int with_bind = bind(&A::foo, arg1, arg2)
(&instance, 7);
Now, of course, you might be looking to assign the lazy functor to a variable. In that respect, I can only recommend BOOST_AUTO:
BOOST_AUTO(afoo, (arg1->*&A::foo)(arg2));
return afoo(&instance, 2);
Which works like a charm.
Full C++03 Sample
See it Live on Coliru
struct A {
A(int f) : f_(f) {}
int foo(int i) {
return f_*i;
}
private:
int f_;
};
#include <boost/phoenix.hpp>
#include <boost/phoenix/function.hpp>
#include <cassert>
int main() {
using namespace boost::phoenix;
using namespace boost::phoenix::arg_names;
A instance(9);
int direct = (arg1->*&A::foo)(arg2)
(&instance, 7);
int with_bind = bind(&A::foo, arg1, arg2)
(&instance, 7);
assert(direct == with_bind);
BOOST_AUTO(afoo, (arg1->*&A::foo)(arg2));
return afoo(&instance, 2);
}

How can I use a boost function to transform the parameter types?

I want to create a boost function object of the following signature:
void (int, boost::uuid);
However, I would like to bind it to a function of the following form:
void (SomeType, boost::uuid)
Where the SomeType argument comes from another function call, so that if I were to call it straight out it would look like:
SomeType myOtherFunction(int);//Prototype
...
myFunction(myOtherFunction(int), myUUID);
In other words, I want the top level function object to completely hide the concept of SomeType and the call to myOtherFunction from the user. Is there a way to do this with one or more boost::function objects created with boost::bind calls?
Functional composition: Live On Coliru
#include <boost/uuid/uuid.hpp>
struct SomeType {};
SomeType myOtherFunction(int) { return SomeType(); }
void foo(SomeType, boost::uuids::uuid) {}
#include <boost/bind.hpp>
#include <boost/function.hpp>
int main()
{
boost::function<void(int, boost::uuids::uuid)> composed;
composed = boost::bind(foo, boost::bind(myOtherFunction, _1), _2);
}
Anyways, in c++11 you'd write [](int i, uuid u) { return foo(myOtherFunction(i), u); } of course