I'm trying to use std::bind and typecast the function arguments to use with a typedef function. However, I can't typecast the std::placeholder. Any ideas to implement what I'm trying to do? For varied reasons, I need to be able to have the typedef function have a uint16_t argument, and also have the init function accept a member function that takes a uint8_t argument). The code (edited for simplicity) that I'm using:
typedef void (write_func_t) (uint16_t, uint8_t);
class MyClass {
public:
MyClass();
template < typename T >
void init(void (T::*write_func)(uint8_t, uint8_t), T *instance) {
using namespace std::placeholders;
_write_func = std::bind(write_func, instance, (uint16_t)_1, _2);
this->init();
}
private:
write_func_t *_write_func;
};
Wouldn't this be cleaner (and much simpler using lambdas and std::function<>)?
class MyClass {
using WriteFunc = std::function<void(int16_t, int8_t)>;
public:
void init(WriteFunc&& func) {
write_func_ = std::move(func);
}
private:
WriteFunc write_func_;
};
Then call in some other type..
class Foo {
// e.g
void SomeWriteFunction(int8_t x, int8_t y) {
}
void bar() {
// The lambda wraps the real write function and the type conversion
mc_inst.init([this](int16_t x, int8_t y) {
this->SomeWriteFunction(x, y);
});
}
};
Related
I have a function that runs a callback:
void run_callback(void(*callback)(uint32_t)) {
callback(100);
}
This works with static functions,
void global_callback(uint32_t);
int main() {
run_callback(global_callback);
}
but not with member functions.
class A {
int x;
public:
void callback(uint32_t);
};
int main() {
A foo;
run_callback(foo.callback);
}
I work around this with a static wrapper function.
void run_member_callback(void* obj, void(*callback)(void*,uint32_t)) {
callback(obj, 100);
}
class B {
int x;
public:
static void static_callback(void* obj, uint32_t value) {
static_cast<B*>(obj)->callback(value);
}
void callback(uint32_t);
};
int main() {
B foo;
run_member_callback(&foo, foo.static_callback);
}
Is there a simple way to pass a member function as an argument?
edit:
I'm trying to avoid STL, and templates aren't an option since my implementation of run_callback is virtual.
You are doing some weird, C-ish things. Use C++ features. I personally would use a template for run_callback and a lambda for passing the member function:
template <class F>
void run_callback(F callback)
{
callback(100);
}
class A
{
int x;
public:
void callback(uint32_t);
};
int main()
{
A foo{};
run_callback([&](uint32_t a) { return foo.callback(a); });
}
If you capture the object by reference take care it outlives the run_callback call. Otherwise capture it by value.
What is a lambda expression in C++11?
I am trying to create a template class which would in turn generate a wrapper over a function. The class will then return the wrapper as result. I would like to use template to have general class that will work with any function with different signatures, such as:
std::function<void()>task = std::bind(fun1, param1, param2);
std::function<int(int, int)>task = std::bind(fun2, param1, param2);
I would like to have something like this:
template <typename T1, typename T2>
class A {
A (string param1, string param2) {
// The created wrapper here i.e. 'task' will be returned by the class.
function<T1>task = bind(T2, param1, param2);
}
// Return the created wrapper in the constructor.
function<T1> returnWrapper() {
return task;
}
};
The code above is mostly a pseudo code since it cannot be compiled, but gives an idea about what I am looking for. Is there any solution for this? I think there should be more than simply use a template for a function's signature. Any help would be highly appreciated. I also would like to be able to pass arbitrary number of parameters to 'bind' if possible.
I think I solved the problem! I had to define a class which takes two type names inside a template and pass one of them to std::function as function signature after currying and use the second one in the constructor to define the curried function (result function after wrapping) in std::bind. Then everything worked fine! There might be some better solution, but this was the best and more or less clear solution I got. Here is the got snippet of the solution I found! Hope it helps the other with the same issue:
#include <iostream>
#include <functional>
using namespace std;
class A {
private:
template <typename T1, typename T2>
class B {
private:
function<T1>ff;
public:
B(T2 fun) {
ff = bind(fun, 1, placeholders::_1);
}
virtual ~B() {
}
int exec(int x) {
return ff(x);
}
};
static int myFun(int x, int y) {
return x + y;
}
public:
A() {
};
int test() {
B<int(int), int (*)(int, int)> b(&myFun);
return b.exec(10);
}
virtual ~A() {
};
};
int main() {
A a;
// Correct result is '11' since we pass 11 and 1 is in the curried function.
cout << "test result: " << a.test() << endl;
return 0;
}
I wrote a C++ class that parses expressions like "2 * SQRT(5) + 1". I've created a class called c_function that "represents" the usual mathematical functions like sqrt, sin, cos etc. something like as follows:
class c_function {
std::string name;
double (*function)(double);
public:
c_function(std::string fname, double (*ffunction)(double)) {
name = fname;
function = ffunction;
}
// ...
};
Then I have a different class that contains a std::vector of these c_function objects:
class expression {
std::vector<c_function> functions;
// etc...
public:
// ctor:
expression(/* ... */) {
// ...
functions.push_back(c_function("SQRT", sqrt));
functions.push_back(c_function("SIN" , sin));
functions.push_back(c_function("COS" , cos));
// ...
}
};
The point is that all these functions have one argument. That is fine for most cases but I want to enable adding custom functions to the expression class and also want to support custom functions with more that one argument (for example, to define a function AREA(a, b) that returns the product of the two values a and b).
I did that by adding an argument counter argumentCount and more function "properties" to the c_function class:
class c_function {
std::string name;
unsigned int argumentCount;
double (*function1)(double);
double (*function2)(double, double);
// ...
};
and used two constructors:
c_function(std::string fname, double (*ffunction)(double)) {
name = fname;
argumentCount = 1;
function1 = ffunction;
function2 = NULL;
};
c_function(std::string fname, double (*ffunction)(double, double)) {
name = fname;
argumentCount = 2;
function1 = NULL;
function2 = ffunction;
};
and added the methods to the expression class:
// add custom function with one argument
void addFunction(std::string fname, double (*ffunction)(double));
// add custom function with two arguments
void addFunction(std::string fname, double (*ffunction)(double, double));
so that one can define
double Expression_Area(double width, double height) {
return (width * height);
}
and introduce it to the expression class with
myExpression.addFunction("AREA", Expression_Area);
That works fine and this way I can also add more function "properties" and functions constructors allowing any number of arguments, but
there is always a limit of the number of arguments that is supported
the code becomes ugly by having multiple constructors, methods to add a function, and code within the interpretation of the expression just because the number of arguments may be different.
I wonder if there is a way to support functions with any number of arguments more general. I tried changing the c_function class to:
class c_function {
std::string name;
unsigned int argumentCount;
double (*function)(...);
// ...
};
but this does not work because functions with fixed number of arguments are not accepted by (...).
Is there any way to get this solved with one constructor, one function "property" etc.?
C++11 onwards
In C++11 you can use a variadic template to declare a class that will take a function with a variable number of arguments:
#include <iostream>
#include <string>
double bar(double x) {
return x;
}
double bar2(double x, double y) {
return x+y;
}
template <typename... Args>
class Foo {
public:
Foo (const std::string& name, double (*func)(Args...))
: name_{name}, func_{func} {}
double call(Args... args) {
return func_(args...);
}
// Thanks to W.F. for reminding me of the operator() overload
// This does the same thing as a call to the "call" method.
double operator()(Args... args) {
return func_(args...);
}
private:
std::string name_;
double (*func_)(Args...);
};
int main() {
Foo<double> t1("test1", bar);
Foo<double, double> t2("test2", bar2);
// NOTE: in C++17 you can declare Foo without the template
// arguments: they will be deduced.
// Foo t1("test1", bar); // C++17
// Foo t2("test2", bar2); // C++17
std::cout << t1.call(14) << ' ' << t2(14, 56) << std::endl;
return 0;
}
You can tweak this basic solution as to how you need your classes to work.
C++98
Pre C++11, you will probably be forced to create classes that take functions with a different number of arguments, so your classes would look something like this:
#include <iostream>
#include <string>
double bar(double x) {
return x;
}
double bar2(double x, double y) {
return x+y;
}
class Foo1 {
public:
// let's typedef the function pointer for two reasons:
// 1. readability
// 2. duplicating the class for a different number of arguments
// means we need to do less modifications to the code because
// we can catch a few changes in one line here.
typedef double (*Function)(double);
Foo1 (const std::string& name, const Function func)
: name_(name), func_(func) {}
double operator()(double x) {
return func_(x);
}
private:
std::string name_;
Function func_;
};
class Foo2 {
public:
typedef double (*Function)(double, double);
Foo2 (const std::string& name, const Function func)
: name_(name), func_(func) {}
double operator()(double x, double y) {
return func_(x, y);
}
private:
std::string name_;
Function func_;
};
// etc. for classes Foo3, Foo4, ... up until you think you will
// need no more.
int main() {
Foo1 t1("test1", bar);
Foo2 t2("test2", bar2);
std::cout << t1(14) << ' ' << t2(14, 56) << std::endl;
return 0;
}
There's a bit of code duplication here, but it's not too bad.
Remarks
Finally, (although I did not show it above because I think it goes without saying) wherever there is code duplication, template the types so that you can reduce this as much as possible. So, for example, you might consider modifying the C++11 Foo class above to:
template <typename T, typename... Args>
class Foo {
public:
typedef T (*Function)(Args...);
Foo (const std::string& name, const Function func)
: name_{name}, func_{func} {}
T operator()(Args... args) {
return func_(args);
}
private:
std::string name_;
Function func_;
};
here is what I would like to do:
typedef std::function<void(const callback&)> callback;
(Ie: defining a std::function that can pass as first arg an object of same type as itself).
However this doesn't compile (callback is not know when parsing argument, even if compiler knows the size of the arg as it's a const ref)
Does anyone knows some kind of hack (perhaps with template?) less ugly than the one I'm using:
struct scallback;
typedef std::function<void(const scallback&)> callback;
struct scallback { callback value; };
It's "ugly" because I have to use arg.value and not arg directly..
NB: I have to use std::function and not C-Like pointer, preventing using void* and cast.
Thanks
Bob
You are right. The type is not known at this point as it has not been defined yet. It's just in the middle of being defined.
What you can try is to inherit a new class from std::function<> instead of type-aliasing it.
You will be able to reference the subclass name in the parent class template instantiation
similarly to CRTP and thanks to C++11 you will be able to import all constructors in a simple line.
This seems to work:
#include <functional>
struct callback : std::function<void(const callback&)> {
using std::function<void(const callback&)>::function;
};
void test(const callback& cb) {}
int main() {
callback cb = test;
test(cb);
return 0;
}
Here is what I have which seems a bit better:
struct callback_arg;
typedef std::function<void(const callback_arg&)> callback;
struct callback_arg : callback // callback_arg can be seen as a callback
{
// callback can be seen as a callback_arg
callback_arg(const callback& a) : callback(a)
{
};
};
void Foo(const callback& val) {};
void Fuu(const callback& val) {};
int main()
{
callback foo = Foo;
callback fuu = Fuu;
foo(fuu); // compiles correctly
return 0;
}
I have several classes which each store and call a callback function. The callback functions' signatures have different parameter and return types, but all of them take just one parameter.
To verify that these classes call their callbacks when they should, I'm trying to write a general test class which (1) provides a callback function which takes one parameter, (2) lets the user query whether that function has been called, and (3) lets the user examine the parameter which was passed to that function. So far, I have something like this:
template<class ReturnType, class ParameterType> class Callable
{
public:
Callable() : m_called(false), m_param() {}
ReturnType operator()(ParameterType param)
{
m_called = true;
m_param = param;
return Returntype();
}
bool Called() { return m_called; }
ParameterType Param() { return m_param; }
private:
bool m_called;
ParameterType m_param;
};
Here's a class which might be tested using class Callable:
#include <boost/function.hpp>
class ToBeTested
{
ToBeTested(boost::function<bool (int)> callback) : m_callback(callback) {};
boost::function<bool (int)> m_callback;
// (methods which should cause the callback to be called here)
};
Here's some test code:
#include <boost/bind.hpp>
int main(int, char**)
{
Callable<bool, int> callable;
ToBeTested tbt(boost::bind(&Callable<bool, int>::operator());
// (tell tbt it should call its callback here)
if (callable.Called()
{
if (EXPECTED_VALUE == callable.Param();
return 0;
}
return -1;
}
This gives me (1) and (2), but there's a problem with (3) when the callback takes its parameter by reference: Callable::m_param is a reference type and therefore can't be default initialised. I could fix that by making Callable::operator() take its parameter by reference, like this:
ReturnType operator()(ParameterType & param)
...but then I can't use class Callable when the callback function takes its parameter by value.
Is there a way to make my test class work regardless of whether the callback function takes its parameter by reference, or do I need to write two nearly-identical test classes?
You could try something like this, where references are actually stored as pointers:
template<typename T>
struct ref_to_ptr
{
typedef T type;
static T wrap(T x) { return x; }
static T unwrap(T x) { return x; }
};
template<typename T>
struct ref_to_ptr<T&>
{
typedef T* type;
static T* wrap(T& x) { return &x; }
static T& unwrap(T* x) { return *x; }
};
template<class ReturnType, class ParameterType> class Callable
{
public:
Callable() : m_called(false), m_param() {}
ReturnType operator()(ParameterType param)
{
m_called = true;
m_param = ref_to_ptr<ParameterType>::wrap(param);
return Returntype();
}
bool Called() { return m_called; }
ParameterType Param() { return ref_to_ptr<ParameterType>::unwrap(m_param); }
private:
bool m_called;
typename ref_to_ptr<ParameterType>::type m_param;
};