Static function definition that resembles a pointer to member function - c++

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

Related

C++ Class vector error, expression must have pointer type

Currently learning some c++ and unsure why this is giving me "expression must have pointer type".
Mapp.hpp
class RouteMap
{
public:
RouteMap();
string getCurrent_();
void StoreCity(string b);
private:
std::vector<string>* cities();
string current_;
};
mapp.cpp
RouteMap::RouteMap(){}
string RouteMap::getCurrent_()
{
return current_;
}
void RouteMap::StoreCity(string b)
{
cities->push_back(b); //Error
}
std::vector<string> RouteMap::cities()
{
return std::vector<string>();
}
I am attempting to have a vector Cities as a private member so that when I run the member function StoreCity(string x), it would push_back the specific string into Cities.
I'm going to take a stab and say that the problem is cities() is a function and requires parenthesis:
cities()->push_back(b);
Edit Just found the implementation of cities() (silly me). You have another problem, and that is that your declaration and implementation don't match.
// declaration
std::vector<string>* cities();
// implementation. Notice the lack of a pointer type return
std::vector<string> RouteMap::cities()
{
return std::vector<string>();
}
It's also weird that you're returning a new vector each time. You probably want a member variable:
class RouteMap
{
//...
private:
std::vector<string> my_cities;
//...
};
and then return the member variable from there:
std::vector<string>* RouteMap::cities()
{
return &my_cities;
}
Edit2: It has come to my attention that you probably, while you could fix these things like this and get it working, the truth is that you probably don't mean for cities() to be a function at all. You probably mean for it to be a member variable instead:
class RouteMap
{
//...
private:
std::vector<string> cities;
//...
};
This requires no implementation, (aka RouteMap::cities(){}), and you can just use it inside any member function (because it's a private member) like current_.

How to pass a object of a class to a function within the object's class function?

I need to pass the object of the class that i'm working on to a function. For me it's hard to explain, so I made a simple example.
I tried using 'this' operator, hoping that it will send 'this' object to the function, but it didn't work. I also tried googling the problem, but I could't find any sensible answers.
#include <iostream>
unsing namespace std;
class apple;
int eatApple(apple & a)
{
a.var1=0;
a.var2=0;
return 0;
}
class apple
{
int var1;
int var2;
void cutApple();
};
void apple::cutApple()
{
var1/=2;
var2/=2;
eatApple(/*HERE I HAVE TO PASS THE OBJECT OF THE CLASS TO THE FUNCTION*/);
}
int main()
{
apple Apple;
Apple.cutApple();
return 0;
}
Note that this code is just a example of the problem. Where i have written in the /* */, that's where i tried the 'this' operator, but i didn't work.
The function header looks like this: int eatApple(apple & a), which means it accepts a reference to apple. this is always a pointer (not a reference), therefore you need to dereference it:
eatApple(*this);

access the own interface with the scope operator doesnt work?

While playing around with polymorphism and templates i eventually dug up a strange (at least for me) behaviour of the scope operator. When i tried to access a method of a *b*aseclass using the *i*nterface with the scope operator within a *d*erived class, i get a linker error. I can only assume that the scope operator doesnt look into the vtable and tries to run the method directly from the interface, which is actually pure virtual.
Here is the example for that:
struct i
{
virtual void set(char* in, short len) = 0;
virtual char* getStr() = 0;
virtual ~i() {}
};
template <int size = 10>
struct b : public i // this one is like an char-Array
{
char str[size];
void set(char* in, short len) { memcpy(this->getStr(),in,len); }
char* getStr() { return str;}
};
template <int size = 10>
struct d : public b<size> // this one is like an cString
{
void set(char* in) { strcpy(this->getStr(),in); }
};
struct final : public d<4>
{
void test()
{
set("abc"); ///< Works
d<4>::set("abc"); ///< Works
//set("abc",3); ///< Error : no matching function for call to 'final::set(const char [4], int)' (its shadowed by d)
//note: candidates are: void d<size>::set(char*) [with int size = 4]
b<4>::set("abc",3); ///< Works
//i::set("abc",3); ///< Linker Error: (.gnu.linkonce.t._ZN5final4testEv+0x68) : Error : undefined reference to `i::set(char*, short)'
//this->set("abc",3); ///< Error : no matching function for call to 'final::set(const char [4], int)' (its shadowed by d too)
((i*) this)->set("abc",3); ///< Works!
}
};
int main()
{
final f;
f.test();
return 0;
}
The background why i tried this, is to avoid changing the template parameter of every call to a templated base class, when i might change the size of the final class.
So can somebody explain me why this happens with the scope operator?
Funny is that it does work, when casting the "this" pointer to a interface pointer and then using the baseclass's method with that. Is this actually valid and practicable?
BTW: i use GCC 4.1.2
EDIT:
Just to clarify, i know d::set is shadowing b::set .. thats not the problem, i am just asking about the linker error!
When you write Base::symbol in a class context, symbol will
always be resolved statically, with name lookup starting in the
class Base. The reason is simple: that's the way you access
masked members in derived classes. Otherwise, you'd be unable
to chain functions, e.g.:
void
Derived::function()
{
Base::function(); // calls the function in Base before doing anything else.
// ...
}
At the time C++ was being developed, this was felt to be
important, and even today, you'd want to support some way of
doing it.
One idea for working around this:
template <int size=10>
struct d : public b<size>
{
typedef b<size> Base;
// ...
};
Then in final, refer to Base::set.
Oh i finally found the answer to my question by myself:
Polymorphism needs a indirection!
As stated here: Polymorphic objects on the stack?
Thanks for pointing THAT out ;)

Static member function pointer to hold non static member function

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

Calling the function pointed by a Pointer-to-Member-Function from within a struct

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)) ();