say I have this program situation overhere:
struct A
{
int(*func_ptr)();
};
struct B
{
int b = 0;
void SetFunctionPointerToLambda(A& a)
{
a.func_ptr = [=] () { return b; };
}
};
int main()
{
A a;
B b;
b.SetFunctionPointerToLambda(a);
}
I want to set a function pointer of an object A to a lambda, which is based of the values of an object B.
So, how is this going to be done?
Current error message:
loeschen5.cc: In member function 'void B::SetFunctionPointerToLambda(A&)':
loeschen5.cc:14:41: error: cannot convert 'B::SetFunctionPointerToLambda(A&)::<lambda()>' to 'int (*)()' in assignment
a.func_ptr = [=] () { return b; };
^
Thanks for any help!
Ok, so I solved this with a functional object:
So, not only the function, but also the necessary variables are stored:
struct FunctionObject
{
const int *b;
int operator ()() const
{
return *b;
}
};
struct A
{
FunctionObject func_ptr;
};
struct B
{
int b = 56;
void SetFunctionPointerToLambda(A& a) const
{
a.func_ptr = FunctionObject { &b };
}
};
int main()
{
A a;
B b;
b.SetFunctionPointerToLambda(a);
}
And it works fine.
Related
For instance I have a function
void func(my_cont &C){
C.membA = 1;
C.membB = 2;
dosomething_with(C);
}
Also what to do in the function, if I have a Struct that does not have a member B?
This is a way to statically check for the existence of a membB member inside the template function.
template<typename T>
void func(T& C)
{
C.membA = 1;
if constexpr (requires() { C.membB; })
{
C.membB = 2;
}
}
int main()
{
struct A
{
int membA;
};
struct B
{
int membA;
int membB;
};
A a;
func(a);
B b;
func(b);
}
Another way to get functionality that differs per type:
Using template specialization, as OP requested.
struct A
{
int membA;
};
struct B
{
int membA;
int membB;
};
template<typename T> void func(T&);
template<> void func<A>(A& a) {
a.membA = 1;
}
template<> void func<B>(B& b) {
b.membA = 1;
b.membB = 2;
}
int main()
{
A a;
func(a);
B b;
func(b);
}
I provide to you a MWE:
#include <iostream>
class C;
class A
{
public:
A(C &cc)
: c(cc)
{
}
int functionA()
{
return 0;
}
C &c;
};
class B
{
public:
B(C &cc)
: c(cc)
{
}
int functionB()
{
return c.a.functionA();
}
C &c;
};
class C
{
public:
C()
: a(*this)
, b(*this)
{
}
int functionC()
{
return b.functionB();
}
A a;
B b;
};
int main()
{
C c;
std::cout << c.functionC() << std::endl;
}
And associated compiler error:
main.cpp: In member function ‘int B::functionB()’:
main.cpp:37:16: error: invalid use of incomplete type ‘class C’
37 | return c.a.functionA();
| ^
main.cpp:5:7: note: forward declaration of ‘class C’
5 | class C;
| ^
Further explanation is probably not required, however, the class C is not fully defined by the time we reach line return c.a.functionA().
What is the most appropriate way to break this interdependence problem?
If it helps to guide, then consider the following context
C = Host
A = CPU
B = RAM
and the actual code where this problem occurs in my project is
void CPU::MemFetchByte(byte &ret, const addr_t addr)
{
HardwareDevice::host.memory.GetByte(ret, addr);
}
perhaps this is useful additional info, perhaps it is not.
Additionally, I tried to invert the problem as follows
#include <iostream>
//class C;
class A;
class B;
class C
{
public:
C()
: a(new A(*this))
, b(new B(*this))
{
}
~C()
{
delete b;
delete a;
}
int functionC()
{
return b->functionB();
}
A *a;
B *b;
};
class A
{
public:
A(C &cc)
: c(cc)
{
}
int functionA()
{
return 0;
}
C &c;
};
class B
{
public:
B(C &cc)
: c(cc)
{
}
int functionB()
{
return c.a->functionA();
}
C &c;
};
int main()
{
C c;
std::cout << c.functionC() << std::endl;
}
however this (as expected) makes things worse not better:
main.cpp:16:24: error: invalid use of incomplete type ‘class A’
16 | : a(new A(*this))
| ^
main.cpp:6:7: note: forward declaration of ‘class A’
6 | class A;
| ^
main.cpp:17:24: error: invalid use of incomplete type ‘class B’
17 | , b(new B(*this))
| ^
main.cpp:7:7: note: forward declaration of ‘class B’
7 | class B;
| ^
Work with complete types by moving the constructors and member function implementations out of the class declarations.
#include <iostream>
class A;
class B;
class C;
class A {
public:
A(C &cc);
int functionA();
C &c;
};
class B {
public:
B(C &cc);
int functionB();
C &c;
};
class C {
public:
C();
int functionC();
A a;
B b;
};
int main()
{
C c;
std::cout << c.functionC() << std::endl;
}
A::A(C &cc) : c(cc)
{ }
int A::functionA() {
return 0;
}
B::B(C &cc) : c(cc)
{ }
int B::functionB() {
return c.a.functionA();
}
C::C() : a(*this), b(*this)
{ }
int C::functionC() {
return b.functionB();
}
int functionB()
{
return c.a.functionA();
}
This function needs to be defined outside of the class body, after class C is defined.
You can apply the same idea to your second attempt (the definitions for C(), ~C(), and functionC() will need to be moved). But this is worse than your first attempt, because you're using heap allocation for no good reason (and class C doesn't follow the rule of three).
It looks like classes A and B are parts of system C, so that another option is to compose C from A and B using derivation. This allows A and B to get to C with a simple downcast, no C& c member is required:
struct C;
struct A {
void fa();
};
struct B {
void fb();
};
struct C : A, B {
void fc();
};
void A::fa() {
static_cast<C&>(*this).fc();
}
void B::fb() {
static_cast<C&>(*this).fc();
}
How to create a function pointer to any class function knowing only arguments and return type? How to call this function later?
I read about std::function, however I do not have an idea how to implement it without using specific class name like "std::function<void(const ClassName&, int)> f_add_display = &ClassName::func;"
The example below is NOT for compiling, it is only to show the idea I mean:
class collection {
p* ...; //pointer to any(!) class function with known arguments and return type
} _collection;
class One {
public:
...
bool Foo_1(int, int) {};
void saveFuncAddr() {_collection.p = this::Foo_1};
};
class Two {
public:
bool Foo_2(int, int) {};
void saveFuncAddr() {_collection.p = this::Foo_2};
};
int main() {
one* = new One();
one->saveFuncAddr();
bool res1 = (*_collection.p)(1, 2);
two* = new Two();
two->saveFuncAddr();
bool res2 = (*_collection.p)(1, 2);
}
First, identifiers beginning with an underscore is reserved in the global namespace, so you shouldn't declare a name like _collection.
You can use lambdas to wrap your member functions:
#include <functional>
struct Collection {
std::function<bool(int, int)> p;
} collection;
class One {
public:
bool Foo_1(int, int) {return true;}
void saveFuncAddr()
{
collection.p = [this](int a, int b){return this->Foo_1(a, b);};
}
};
class Two {
public:
bool Foo_2(int, int) {return true;}
void saveFuncAddr()
{
collection.p = [this](int a, int b){return this->Foo_2(a, b);};
}
};
int main() {
auto one = new One();
one->saveFuncAddr();
bool res1 = (collection.p)(1, 2);
delete one;
auto two = new Two();
two->saveFuncAddr();
bool res2 = (collection.p)(1, 2);
delete two;
}
I am trying to associate a struct's member variable with a class. So that when I create a new class, I can specify that it is associated with this member variable in a struct. For example:
struct A {
int a;
int b;
};
static A a[2];
a[0].a = 1;
a[0].b = 2;
a[1].a = 3;
a[1].b = 4;
class foo {
public:
foo(int index, ???) {
c = a[index].???; //Is it possible to define the 2nd parameter as a getter of struct A's member? So this line could resolve to either a[index].a or a[index].b?
}
private:
int c;
};
So that:
new foo(0, ???) would set c to 1 given ??? refer to A::a
new foo(0, ???) would set c to 2 given ??? refer to A::b
new foo(1, ???) would set c to 3 given ??? refer to A::a
new foo(1, ???) would set c to 4 given ??? refer to A::b
Yes, it is possible, you need to pass a data member pointer:
#include <iostream>
struct A
{
int a;
int b;
};
static A a[2]
{
1, 2
, 3, 4
};
class foo
{
public: int c;
public:
foo(int const index, int A::* const p_field)
{
c = a[index].*p_field;
}
};
int main()
{
foo const f1(0, &A::a);
::std::cout << f1.c << ::std::endl;
foo const f2(0, &A::b);
::std::cout << f2.c << ::std::endl;
foo const f3(1, &A::a);
::std::cout << f3.c << ::std::endl;
foo const f4(1, &A::b);
::std::cout << f4.c << ::std::endl;
return 0;
}
Check this code at online compiler
You have a couple options. If you just want the integer (like you have in your code you've posted), then just take an integer as a parameter to the constructor and pass it the right number.
class foo {
public:
foo(int val) {
c = val
}
private:
int c;
};
int main() {
foo f(a[0].b);
}
Or you could take a reference to an integer. This way if one changes, the other will as well:
class foo {
public:
foo(int &val) : c(val) { } //need to use an initialization list for this one
private:
int &c;
};
int main() {
foo f(a[0].b);
a[0].b = -1; //f.c will be -1 now as well
}
Using a data member pointer as in VTT's answer is the most direct solution but I often find member pointers and member function pointer syntax a bit cumbersome and I believe it is hard for the compiler to optimize.
For these kind of things I prefer to use a stateless lambda. You can pass a lambda to a function template and then the compiler can easily optimize it away:
#include <iostream>
struct A {
int a;
int b;
};
static A a[2]{{1, 2}, {3, 4}};
class foo {
public:
int c;
public:
template<typename F>
foo(int index, F getter) { c = getter(a[index]); }
};
int main() {
auto agetter = [](const A& a){ return a.a; };
auto bgetter = [](const A& a){ return a.b; };
foo const f1(0, agetter);
std::cout << f1.c << "\n";
foo const f2(0, bgetter);
std::cout << f2.c << "\n";
foo const f3(1, agetter);
std::cout << f3.c << "\n";
foo const f4(1, bgetter);
std::cout << f4.c << "\n";
}
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