This has defeated me. I want to have a static class variable which is a pointer to a (non-static) member function. I've tried all sorts of ways, but with no luck (including using typedefs, which just seemed to give me a different set of errors). In the code below I have the static class function pointer funcptr, and I can call it successfully from outside the class, but not from within the member function CallFuncptr - which is what I want to do. Any suggestions?
#include <stdio.h>
class A
{
public:
static int (A::*funcptr)();
int Four() { return 4;};
int CallFuncptr() { return (this->*funcptr)(); }
// doesn't link - undefined reference to `A::funcptr'
};
int (A::*funcptr)() = &A::Four;
int main()
{
A fred;
printf("four? %d\n", (fred.*funcptr)()); // This works
printf("four? %d\n", fred.CallFuncptr()); // But this is the way I want to call it
}
Try this instead:
#include <iostream>
class A {
public:
typedef int (A::*AMemFn)();
static AMemFn funcptr;
int Four() { return 4; }
int CallFuncptr() { return (this->*funcptr)(); }
};
A::AMemFn A::funcptr = &A::Four;
int main()
{
A fred;
std::cout << "four? " << fred.CallFuncptr() << std::endl;
}
jweyrich has a nice looking work around (and I suggest you use it), but I thought I'd elaborate on what the real problem in the code is:
Your problem is this line:
int (A::*funcptr)() = &A::Four;
This is defining a global variable called funcptr that is of the right type, rather than A::funcptr.
What you need is this mess:
int (A::*(A::funcptr))() = &A::Four;
This ugly mess is why I suggest you go down the typedef path to get a nice looking version like jweyrich's solution.
A static variable is not a member of a particular object -- it can only be accessed through the classes namespace. CallFuncptr should be rewritten:
int CallFuncptr() { return (*funcptr)();
which I think should work, since this function can access functions in A's namespace without specifying it.
Also, function pointers are more of a C construct than C++. You can access the static variable outside the class with the code:
A::CallFuncptr
since CallFunctptr just resides in A's namespace
Related
In my program (this is only a short version), I have a struct that has 9 members (airplanes) which all have the same variables.
struct FlightP {string FLID; int altitude; int heading; flightMode; } ArrP_1, ArrP_2;//1-9 etc
If I want to change for example the altitude of members ArrP_1 and ArrP_2 I did it like so:
int main(){
ArrP_1.altitude = 10000;
ArrP_2.altitude = 10000;
}
But is there a way to use a function like that:
void ALtChange(FlightP flight_p){
flight_p.altitude = 12000;
}
int main(){
ALtChange(ArrP_1);
ALtChange(ArrP_2);
//If I have to change multiple parameters in multiple members at the same time this function would make things easier.
}
Somewhy this function doesn't do anything. Is the function wrong or what should I do differently?
Somewhy this function doesn't do anything.
Your function modifies the function argument that is local to the function.
In order to modify a variable from another scope, you can use indirection: Use a reference argument.
Instead of modiying the object in the function, another approach is to write a function that returns a ALtChange object, and you can assign the result to a variable to modify it.
It's like #Jonnhy Mopp said, pass it by reference like so:
#include <iostream>
#include <string>
using namespace std;
struct FlightP {string FLID; int altitude; int heading; int flightMode; } ArrP_1, ArrP_2;//1
void ALtChange(FlightP& flight_p) { flight_p.altitude = 12000; }
void print_altitude(const FlightP& flight) { std::cout << flight.altitude << std::endl; }
int main(){
ArrP_1.altitude = 10000;
ArrP_2.altitude = 10000;
ALtChange(ArrP_1);
ALtChange(ArrP_2);
print_altitude(ArrP_1);
print_altitude(ArrP_2);
}
Is there any technique or compiler extension keyword to declare class member variables inside class member functions? Something like
struct test_t{
void operator ()(){
instance_local int i = 0;
}
};
The best that came in my mind was using thread_local and then executing the member function inside another thread, but this would be too ugly to be useful.
EDIT: example
Well I'm really sorry for the following probably confusing example (it is related to my question yesterday Is there any problem in jumping into if(false) block?). I really tried to make a less confusing up...
#include <iostream>
#define instance_local thread_local
struct A{
A(int i) :
i(i)
{
}
void dosomethinguseful(){
std::cout << i << std::endl;
}
int i;
};
struct task1{
int part;
task1() : part(0){}
void operator ()(){
int result_of_calculation;
switch (part) {
case 0:{
//DO SOME CALCULATION
result_of_calculation = 5;
instance_local A a(result_of_calculation);
if(false)
case 1:{ a.dosomethinguseful();}
part++;
}
default:
break;
}
}
};
int main(){
task1 t;
t();
t();
return 0;
}
instance_local A a(result_of_calculation); that is what i could get from such a keyword instead of making a smart pointer for a.
You're describing a coroutine. Here a rough draft of what it could look like (I'm not an expert in coroutine)
auto task1() -> some_awaitable_type {
result_of_calculation = 5;
A a(result_of_calculation);
co_yield;
a.dosomethinguseful();
}
This could be called like this:
some_awaitable_type maybe_do_something = task1();
// calculation done here
// dosomethinguseful called here
co_await maybe_do_something();
There is not. The compiler needs to know the structure of the class without compiling all the method implementations. If you could slip instance_local int foo into a method body, that would make the size of the data structure 4 bytes larger.
On a more principled level, it's not good to hide data. The equivalent feature for global variables that you might be thinking of, static local variables, is a carryover from C that is widely considered to be an anti-pattern:
Why are static variables considered evil?
Not directly, no.
You could define a:
static std::map<test_t*, int> is;
…where the first part of each element is a this pointer.
But, why?
Make a member variable.
I want to implement a function that can print out the value of one member variable (for example, 'aa') of struct ('Data') by it's name.
I try to use the macro definition as follows, but failed.
Is there a simple way to implement it?
#include <string>
#include <iostream>
using namespace std;
struct Data
{
int aa;
int bb;
int cc;
Data(): aa(1),bb(2),cc(3) {};
};
#define Param(a,b) a.##b
void Process(Data& data, const string& name)
{
cout << Param(data, name) << endl;
}
void main()
{
Data data;
Process(data, "aa");//I want print the value of Data.aa
Process(data, "bb");//I want print the value of Data.bb
Process(data, "cc");//I want print the value of Data.cc
}
This is not possible in C++.
This kind of usage is generally seen in scripting languages.
In C++ the variable names are constructed at compile time.
Your original code sample makes no sense to me because if you call Param(name) then the compiler has to know what instance of Data it has to use to determine the value of the member variable you want to get the value of (but I'm neither an expert using macros nor do I like them very much).
I tried to solve your problem using the following approach:
struct Data
{
int aa;
};
#define GetMemberValue(d, n) d.##n
int main()
{
Data d;
d.aa = 3;
int i = GetMemberValue(d, aa);
}
At least this approach returns the right result in this case.
Another thing is that you stated that you cannot call the member variables directly i.e. data.aa so you might run into the same issue using the macro. It's just a guess as I don't know the original code you're using.
I'm looking into the LLVM source code and I never encountered the following syntax:
class BasicBlock {
public:
typedef iplist<Instruction> InstListType;
private:
InstListType InstList;
static iplist<Instruction> BasicBlock::*getSublistAccess(Instruction*) {
return &BasicBlock::InstList;
}
}
what does the above define? At first it seemed a normal static function but I don't understand the BasicBlock::* part. Seems like a static function which returns a member function pointer and that directly executes that member function's code.
The return type of static member function getSublistAccess is
iplist<Instruction> BasicBlock::*
that is, a pointer to a non-static data member of class BasicBlock, where the data type is iplist<Instruction>.
What getSublistAccess actually returns is &BasicBlock::InstList, that is exactly a non-static data member of class BasicBlock, where the data type is InstListType. i.e., iplist<Instruction>.
Is a function pointer.
You can read this article for detail.
Thanks to iavr for the answer. I'm awarding the answer to him but I'd like to add some details here which will hopefully help someone reading this post.
What I asked and as iavr explained to me, might be understood with the following code:
#include <iostream>
using namespace std;
struct customType {
int b;
};
struct Instruction {};
class BasicBlock {
public:
BasicBlock(int a) { InstList.b = a; }
customType InstList;
static customType BasicBlock::*getSublistAccess(Instruction*) {
return &BasicBlock::InstList;
}
};
int main() {
BasicBlock bb(90);
Instruction justForSignature;
// Get a pointer to a member of type customType through the static function
customType BasicBlock::* ptrToMember = BasicBlock::getSublistAccess(&justForSignature);
cout << (bb.*ptrToMember).b; // Parenthesis are necessary, '.' has higher precedence on *
// Output: 90
return 0;
}
Try it out: http://ideone.com/hYgfh8
I have a class Test with a peculiar data structure.
A member of class Test is a std::map where the key is a std::string and the mapped value is a struct defined as follows:
typedef struct {
void (Test::*f) (void) const;
} pmf_t;
Initialization of the map is OK. The problem is when I am trying to call the function pointed. I made up a toy example reproducing the problem. Here it is:
#include <iostream>
#include <map>
using namespace std;
class Test;
typedef void (Test::*F) (void) const;
typedef struct {
F f;
} pmf_t;
class Test
{
public:
Test () {
pmf_t pmf = {
&Test::Func
};
m["key"] = pmf;
}
void Func (void) const {
cout << "test" << endl;
}
void CallFunc (void) {
std::map<std::string, pmf_t>::iterator it = m.begin ();
((*it).second.*f) (); // offending line
}
std::map<std::string, pmf_t> m;
};
int main ()
{
Test t;
t.CallFunc ();
return 0;
}
Thanks in advance,
Jir
The name of the pmf_t type is f, so the first change is to remove the * to get second.f. That gives you a pointer-to-member value. To use a pointer-to-member, you need an instance. The only one you have available of the correct type is this, so use it with the ->* operator:
(this->*it->second.f)();
You need parentheses around the whole thing, or else the compiler thinks you're trying to call it->second.f() (which isn't allowed) and then applying the result to ->*.
The offending line is trying to call a member function without any object to call it on. If the intention is to call it for the this object, I believe the call should look like
( this->* ((*it).second.f) )();
Where this->* is the syntax for dereferencing a pointer-to-member for the current object. ((*it).second.f) is the pointer retrieved from the map, and () is the call operator for actually calling the function.
This is perhaps good as an exercise, but otherwise of limited use.
I think you might want to check out the C++ FAQ on this one. The syntax is apparently pretty tricky to get right (they actually recommend using a macro).
It might be too late for this question but, the seemingly complex synatax can be break down to two simple lines so it looks pretty clear:
void CallFunc (void)
{
pmf_t t = m["key"]; //1>get the data from key
(this->*t.f)(); //2>standard procedure to call pointer to member function
}
try this:
(this->*((*it).second.f)) ();