I have two methods which have almost the same code except for two methods they call (and some other details I can easily parameterize). However, those method calls have the same signature, so I think I can generalize them into a single method.
class A{
IApi* m_pApi;
void M1();
void M2();
public:
void DoThings();
}
void A::M1(){
int i;
bool b;
m_pApi->method1( &i, &b );
//Other stuff...
}
void A::M2(){
int i;
bool b;
m_pApi->method2( &i, &b );
//Other stuff...
}
void A::DoThings(){
M1();
M2();
}
I can figure out how to "parameterize" the "Other stuff" code, but the problem are the calls to method1 and method2. I think I have to use std::bind somehow, but I can't do something like this...
void A::M( std::function<void(int*,bool*)> f ){
int i;
bool b;
f( &i, &b );
}
void A::DoThings(){
M( std::bind( ???, m_pApi ) ); //M1
M( std::bind( ???, m_pApi ) ); //M2
}
The problem here is that m_pApi is not a concrete class (it's an interface implemented by a bunch of concrete classes), so I'm not sure if I can do the usual &Class::Method thing. Suggestions?
Use pointers to member function.
#include <iostream>
using namespace std;
struct IApi {
void method1(int * i, bool * b) {
*i = 1; *b = true;
}
void method2(int * i, bool * b) {
*i = 2; *b = false;
}
};
class A {
IApi* m_pApi;
void M(void (IApi::*)(int*, bool*));
public:
A() : m_pApi(new IApi()) {}
void DoThings();
};
void A::M(void (IApi::*mptr)(int*, bool*)) {
int i;
bool b;
(m_pApi->*mptr)( &i, &b );
cout << i << ' ' << b << endl;
}
void A::DoThings(){
M(&IApi::method1);
M(&IApi::method2);
}
int main() {
A a;
a.DoThings();
}
Related
I want to know if there is an approach to decrease the number of overloaded function (function edit) in the below code.
class foo
{
public:
foo(int _a, char _b, float _c) : a(_a), b(_b), c(_c){};
void edit(int new_a);
void edit(char new_b);
void edit(float new_c);
void edit(int new_a, char new_b);
void edit(int new_a, float new_c);
void edit(char new_b, float new_c);
void edit(int new_a, char new_b, float new_c);
void info();
private:
int a;
char b;
float c;
};
Here is the implementation of the edit functions :
void foo::edit(int new_a)
{
a = new_a;
}
void foo::edit(char new_b)
{
b = new_b;
}
void foo::edit(float new_c)
{
c = new_c;
}
void foo::edit(int new_a, char new_b)
{
a = new_a;
b = new_b;
}
void foo::edit(int new_a, float new_c)
{
a = new_a;
c = new_c;
}
void foo::edit(char new_b, float new_c)
{
b = new_b;
c = new_c;
}
void foo::edit(int new_a, char new_b, float new_c)
{
a = new_a;
b = new_b;
c = new_c;
}
The edit function will let the user change the parameters of the object as he wishes.
But the thing is that if we add a new parameter we have to add to many overloaded function and I thought there should be a better way.
Here with 3 parameters we need 7 overloaded functions but if we had 4 parameters (a, b, c and d) then we had to develop 14 overloaded function!
That's why I think there should be a better approach.
Thanks.
With variadic and (ab)using std::get<T> on std::tuple, you might do
template <typename... Ts>
void edit(Ts... values)
{
((std::get<Ts&>(std::tie(a, b, c)) = std::get<Ts&>(std::tie(values...))), ...);
}
Demo.
Note: I use std::get<Ts&>(std::tie(values...)) instead of simply values to get error with duplicated input types(edit(42, 42);).
You can avoid the huge number of overloads and still allow the caller to set more than one member in a single expression:
class foo
{
public:
foo(int _a, char _b, float _c) : a(_a), b(_b), c(_c){};
foo& edit(int new_a) { a = new_a; return *this;}
foo& edit(char new_b) { b = new_b; return *this; }
foo& edit(float new_c) { c = new_c; return *this; }
private:
int a;
char b;
float c;
};
int main() {
foo f(1,'c',2.0);
f.edit(42).edit(42.0f).edit('a');
}
Adding a member requires you to write one overload rather than N to support all combinations.
The previous solutions are quite fine, but suppose that all elements have a different type.
A possibility is to still use a variadic template, and in the call to indicate with a string which element must be modified.
This would allow the possibility to have the same type for different elements.
#include <iostream>
#include <string>
class foo {
public:
foo(int _a, char _b, float _c) : a(_a), b(_b), c(_c){};
void edit() {};
template<typename T1, typename... T2>
void edit (const std::string& id, T1 var1, T2... var2) {
if (id == "a") a = var1;
else if (id == "b") b = var1;
else if (id == "c") c = var1;
edit(var2...);
};
void info();
//private:
int a;
char b;
float c;
};
std::ostream& operator<<(std::ostream& os, const foo& obj) {
std::cout << "a = " << obj.a << " b = " << obj.b << " c = " << obj.c;
return os;
}
int main() {
foo example(1, 'a', 2.0);
example.edit("c", 3.0f, "b", 'g', "a", 5);
std::cout << example << std::endl;
}
Given your edit functions that modify a single member:
void edit(int new_a)
{
a = new_a;
}
void edit(char new_b)
{
b = new_b;
}
void edit(float new_c)
{
c = new_c;
}
You can define a single function in C++11 using variadic templates to support multiple parameters in terms of multiple calls with a single parameter:
template< typename FirstType, typename ...OtherTypes >
void edit(FirstType ft, OtherTypes ...ot)
{
edit(ft);
edit(ot...);
}
Using C++17, fold expressions can make this function even simpler.
template< typename ...Types >
void edit(Types ...types)
{
(edit(types), ...);
}
Note: This solution will not try to prevent multiple changes to the same type, such as edit(1, 2, 3);
I want to avoid duplicated code in this usecase
class A {
protected:
virtual void A1(const void* const s, const std::streamsize n) const;
inline void A2(const void* const s, const std::streamsize n) const;
};
class B : public A {
private:
const char *a;
void B1(const char *b) {
if (!b) {
return;
}
if (a < b) {
A1(a, b-a);
}
}
void B2(const char *b) {
if (!b) {
return;
}
if (a < b) {
A2(a, b-a);
};
}
};
So, as you can see above in both B1() and B2() there is duplicate code (that check for b) except for the call inside that if (note that the if condition is the same). I think this ifmakes somehow inconvenient to extract a new method, but also I think it can be done using lambdas and/or templates. There is no point of interest on how A1() and A2() are implemented for this usecase.
My question: What is the best and simplest way to avoid this duplication of code ?
You can write a function that accepts pointer to member to be executed
class B : public A {
private:
const char *a;
using F = void(A::*)(const void* const, const std::streamsize) const;
void RunFun(F f, const char *b) {
if (!b) {
return;
}
if (a < b) {
(this->*f)(a, b-a);
}
}
void B1(const char *b) {
RunFun(&B::A1,b);
}
void B2(const char *b) {
RunFun(&B::A2,b);
}
};
Another (simplified) example, using lambda and std::function
#include <cstring>
#include <iostream>
#include <functional>
struct A
{
virtual void A1 (char const * const b)
{ std::cout << b << "\n- A1 call" << std::endl; }
void A2 (char const * const b)
{ std::cout << b << "\n- A2 call" << std::endl; }
};
struct B : public A
{
const char * a;
std::function<void(char const * const, void(A::*)(char const * const))>
funcA { [this](char const * const b, void(A::*f)(char const * const))
{ if ( b && std::strlen(b) ) (this->*f)(b); } };
void B1 (char const * b)
{ funcA(b, &A::A1); }
void B2 (char const * b)
{ funcA(b, &A::A2); }
};
int main ()
{
B b;
b.B1("- B1 call");
b.B2("- B2 call");
}
I'll describe my question using the following sample code.
I have class B defined as follows:
class B
{
public:
inline B(){}
inline B(int(*f)(int)) :myfunc{ f }{}
void setfunction(int (*f)(int x)) { myfunc = f; }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
int(*myfunc)(int);
};
I then define class A as follows:
class A
{
public:
A(int myint) :a{ myint }{ b.setfunction(g); }
int g(int) { return a; }
void print() { b.print(a); }
private:
B b;
int a;
};
To me the issue seems to be that the member function g has the signature int A::g(int) rather than int g(int).
Is there a standard way to make the above work? I guess this is quite a general setup, in that we have a class (class B) that contains some sort of member functions that perform some operations, and we have a class (class A) that needs to use a particular member function of class B -- so is it that my design is wrong, and if so whats the best way to express this idea?
You can use std::function:
class B
{
public:
inline B() {}
inline B(std::function<int(int)> f) : myfunc{ f } {}
void setfunction(std::function<int(int)> f) { myfunc = f; }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
std::function<int(int)> myfunc;
};
class A
{
public:
A(int myint) :a{ myint } {
b.setfunction([this](int a) {
return g(a);
}
);
}
int g(int) { return a; }
void print() { b.print(a); }
private:
B b;
int a;
};
You could generalize the class B. Instead of keeping a pointer (int(*)(int)), what you really want is any thing that I can call with an int and get back another int. C++11 introduced a type-erased function objection for exactly this reason: std::function<int(int)>:
class B
{
using F = std::function<int(int)>
public:
B(){}
B(F f) : myfunc(std::move(f)) { }
void setfunction(F f) { myfunc = std::move(f); }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
F myfunc;
};
And then you can just provide a general callable into B from A:
A(int myint)
: b([this](int a){ return g(a); })
, a{ myint }
{ }
Use std::function and std::bind
class B
{
public:
inline B(int(*f)(int)) :myfunc{ f }{}
void setfunction(std::function<int(int)> f) { myfunc = f; }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
std::function<int(int)> myfunc;
};
// ...
A a;
B b(std::bind(&A::g, &a));
Also note that you should initialize the function pointer to some default value (most likely null) and check for it when using, otherwise it's value is undefined.
You could use std::bind to bind the member function A::g.
class B
{
public:
inline B(){}
inline B(std::function<int(int)> f) :myfunc{ f }{}
void setfunction(std::function<int(int)> f) { myfunc = f; }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
std::function<int(int)> myfunc;
};
class A
{
public:
A(int myint) :a{ myint } {
b.setfunction(std::bind(&A::g, this, std::placeholders::_1));
}
int g(int) { return a; }
void print() { b.print(a); }
private:
B b;
int a;
};
Note you need to change the type of functor from function pointer to std::function, which is applicable with std::bind.
LIVE
I would like to do the following:
I have two classes, A and B, and want to bind a function from A to a function from B so that whenever something calls the function in B, the function from A is called.
So basically, this is the scenario:
(important A and B should be independent classes)
This would be class A:
class A {
private:
// some needed variables for "doStuff"
public:
void doStuff(int param1, float *param2);
}
This is class B
class B {
private:
void callTheFunction();
public:
void setTheFunction();
}
And this is how I would like to work with these classes:
B *b = new B();
A *a = new A();
b->setTheFunction(a->doStuff); // obviously not working :(
I've read that this could be achieved with std::function, how would this work? Also, does this have an impact in the performance whenever callTheFunction() is called? In my example, its a audio-callback function which should call the sample-generating function of another class.
Solution based on usage C++11 std::function and std::bind.
#include <functional>
#include <stdlib.h>
#include <iostream>
using functionType = std::function <void (int, float *)>;
class A
{
public:
void doStuff (int param1, float * param2)
{
std::cout << param1 << " " << (param2 ? * param2 : 0.0f) << std::endl;
};
};
class B
{
public:
void callTheFunction ()
{
function (i, f);
};
void setTheFunction (const functionType specificFunction)
{
function = specificFunction;
};
functionType function {};
int i {0};
float * f {nullptr};
};
int main (int argc, char * argv [])
{
using std::placeholders::_1;
using std::placeholders::_2;
A a;
B b;
b.setTheFunction (std::bind (& A::doStuff, & a, _1, _2) );
b.callTheFunction ();
b.i = 42;
b.f = new float {7.0f};
b.callTheFunction ();
delete b.f;
return EXIT_SUCCESS;
}
Compile:
$ g++ func.cpp -std=c++11 -o func
Output:
$ ./func
0 0
42 7
Here's a basic skeleton:
struct B
{
A * a_instance;
void (A::*a_method)(int, float *);
B() : a_instance(nullptr), a_method(nullptr) {}
void callTheFunction(int a, float * b)
{
if (a_instance && a_method)
{
(a_instance->*a_method)(a, b);
}
}
};
Usage:
A a;
B b;
b.a_instance = &a;
b.a_method = &A::doStuff;
b.callTheFunction(10, nullptr);
This i basic a solution
class A {
private:
// some needed variables for "doStuff"
public:
void doStuff(int param1, float *param2)
{
}
};
typedef void (A::*TMethodPtr)(int param1, float *param2);
class B {
private:
TMethodPtr m_pMethod;
A* m_Obj;
void callTheFunction()
{
float f;
(m_Obj->*m_pMethod)(10, &f);
}
public:
void setTheFunction(A* Obj, TMethodPtr pMethod)
{
m_pMethod = pMethod;
m_Obj = Obj;
}
};
void main()
{
B *b = new B();
A *a = new A();
b->setTheFunction(a, A::doStuff); // now work :)
}
This is related to this previous question: Using boost::bind with boost::function: retrieve binded variable type.
I can bind a function like this:
in .h:
class MyClass
{
void foo(int a);
void bar();
void execute(char* param);
int _myint;
}
in .cpp
MyClass::bar()
{
vector<boost::function<void(void)> myVector;
myVector.push_back(boost::bind(&MyClass::foo, this, MyClass::_myint);
}
MyClass::execute(char* param)
{
boost::function<void(void)> f = myVector[0];
_myint = atoi(param);
f();
}
But how can I bind a return value ? i.e.:
in .h:
class MyClass
{
double foo(int a);
void bar();
void execute(char* param);
int _myint;
double _mydouble;
}
in .cpp
MyClass::bar()
{
vector<boost::function<void(void)> myVector;
//PROBLEM IS HERE: HOW DO I BIND "_mydouble"
myVector.push_back(boost::bind<double>(&MyClass::foo, this, MyClass::_myint);
}
MyClass::execute(char* param)
{
double returnval;
boost::function<void(void)> f = myVector[0];
_myint = atoi(param);
//THIS DOES NOT WORK: cannot convert 'void' to 'double'
// returnval = f();
//MAYBE THIS WOULD IF I COULD BIND...:
// returnval = _mydouble;
}
If what you want is a nullary function that returns void but assigns a value to _myDouble with the result of foo() before doing so, then you cannot do this easily with just Boost.Bind. However, Boost has another library specifically catered to this sort of thing -- Boost.Phoenix:
#include <iostream>
#include <vector>
#include <boost/function.hpp>
#include <boost/phoenix/phoenix.hpp>
struct MyClass
{
MyClass() : _myVector(), _myInt(), _myDouble() { }
void setMyInt(int i);
void bar();
void execute();
private:
double foo(int const a) { return a * 2.; }
std::vector<boost::function<void()> > _myVector;
int _myInt;
double _myDouble;
};
void MyClass::setMyInt(int const i)
{
_myInt = i;
}
void MyClass::bar()
{
using boost::phoenix::bind;
_myVector.push_back(
bind(&MyClass::_myDouble, this) =
bind(&MyClass::foo, this, bind(&MyClass::_myInt, this))
);
}
void MyClass::execute()
{
if (_myVector.empty())
return;
_myVector.back()();
double const returnval = _myDouble;
std::cout << returnval << '\n';
}
int main()
{
MyClass mc;
mc.bar();
mc.setMyInt(21);
mc.execute(); // prints 42
mc.setMyInt(3);
mc.execute(); // prints 6 (using the same bound function!)
// i.e., bar has still only been called once and
// _myVector still contains only a single element;
// only mc._myInt was modified
}
problem 1: myVector needs to be a class member.
problem 2: myVector is interested in functions that return doubles and take no arguments, which would be boost::function<double()>
then, to bind _mydouble to the parameter of foo, call boost::bind(&MyClass::foo, this, MyClass::_mydouble) which should give you a compilation warning about casting a double to an int for when foo is called.
The closest you can come with Boost.Bind is providing the toreturn as a parameter.
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
using namespace std;
class Foo {
int myInt;
double myDouble;
public:
Foo() : myInt(3), myDouble(3.141592) { }
void SetToMyInt(double& param)
{
param = myInt;
}
void SetToMyDouble(double& param)
{
param = myDouble;
}
double Execute()
{
double toReturn = 2;
boost::function<void(double&)> f = boost::bind(&Foo::SetToMyDouble, this, _1);
f(toReturn);
return toReturn;
}
};
int main() {
Foo foo;
std::cout << foo.Execute() << std::endl;
return 0;
}