Is this possible? If so, I can't seem to get the syntax right. (C++ function pointer)
bit of background. The code below has been shorten for this post. The reason for this implementation is to avoid an endless list of SWITCH/CASE or IF/ELSEIF statements; and have an endless list of DECODER_FUNCTION_TABLE (see below). This code deals with an industry standard that uses mnemonics to mean different things and there are hundreds of these mnemonics. So this portion of my code is to decode certain mnemonics pass to it from another section of code that loops through a passed in record... anyway my difficulty is in keeping a member function pointer in a structure outside of the class...
Have a look. I think the code may do a better job explaining ;)
typedef struct _DECODER_FUNCTION_RECS
{
ISO_MNEMONIC_ID Mnemonic;
void (Database::*pFn)(Database::Rec *);
}DECODER_FUNCTION_RECS;
DECODER_FUNCTION_RECS DECODER_FUNCTION_TABLE[] = {
SFP, &Database::Decode_SFP,
KOG, &Database::Decode_KOG
};
void Database::DecodedDescription(Rec *A)
{
int i = 0;
bool Found = false;
while( i < DECODER_FUNCTION_TABLE_COUNT && !Found )
{
if( DECODER_FUNCTION_TABLE[i].Mnemonic == A->Mnemonic )
Found = true;
else
i++;
}
if( Found )
(([DECODER_FUNCTION_TABLE[i]).*this.*pFn)( A );
}
void Database::Decode_SFP(Rec *A)
{
// do decode stuff on A
}
The detail I'm trying to work out is this line:
(([DECODER_FUNCTION_TABLE[i]).*this.*pFn)( A );
You call a member function pointer (that's what it's called) with
(this->*DECODER_FUNCTION_TABLE[i].pFn)(A);
Could put parens around DECODER_FUNCTION_TABLE[i].pFn, but the member access operator . has a higher precedence than member function operator ->*.
I wrote up a few simple examples that will shed some light the other day
It's in my answer to this question
error C2664 and C2597 in OpenGL and DevIL in C++
Or a direct link to codepad
Related
I have a function which processes data that comes as a sequence. Because of this, I need to know the value of certain variables from the last function call during the current function call.
My current approach to doing this is to use static variables. My function goes something like this:
bool processData(Object message){
static int lastVar1 = -1;
int curVar1 = message.var1;
if (curVar1 > lastVar1){
// Do something
}
lastVar1 = curVar1;
}
This is just a small sample of the code; in reality I have 10+ static variables tracking different things. My gut tells me using so many static variables probably isn't a good idea, though I have nothing to back that feeling up.
My question: Is there a better way to do this?
An alternative I've been looking into is using an object whose fields are lastVar1, lastVar2, etc. However, I'm not sure if keeping an object in memory would be more efficient than using static variables.
Your question has a taste of being purely about style and opinions, though there are aspects that are not a matter of opinion: multithreading and testing.
Consider this:
bool foo(int x) {
static last_val = -1;
bool result = (x == last_val);
last_val = x;
return result;
}
You can call this function concurrently from multiple threads but it wont do the expected. Moreover you can only test the function by asserting that it does the right thing:
foo(1);
assert( foo(1) ); // silenty assumes that the last call did the right thing
To setup the preconditions for the test (first line) you already have to assume that foo(1) does the right thing, which somehow defeats the purpose of testing that call in the second line.
If the methods need the current object and the previous object, simply pass both:
bool processData(const Object& message,const Object& previous_message){
if (message.var1 > previous_message.var1){
// Do something
return true;
}
return false;
}
Of course this just shifts the issue of keeping track of the previous message to the caller, though thats straight-forward and requires not messing around with statics:
Object message, old_message;
while ( get_more( message )) {
processData(message, old_message);
old_message = message;
}
This question might have been answered before, but searching around and using google didn't bring me there, so I'll ask.
I'm currently making a game and working on collision, however, for some reason it seems like whenever I try to compile I get a ISO C++ forbids comparison between pointer and integer
At first I thought I might have something wrong in my syntax which I checked, but wasn't able to find anything, so I just left the line of code to this:
if((getMinX() > c->getMinX()) && (getMinX() < c-getMaxX()))
I tried adding this-> or adding parenthesis, but that doesn't seem to work, however, just doing
if(this->getMinX() > c->getMinX())
seems to work fine as well as
if((5 > 3) && (5 < 10))
Is there something I'm missing?
Both objects are derived from a class called Collideable defined like this
class Collideable
{ public:
bool collidesWith(Collideable*);
virtual int getMinX() = 0;
virtual int getMaxX() = 0;
virtual int getMinY() = 0;
virtual int getMaxY() = 0;
};
All classes properly override from the virtual methods and the code causing the issue is in bool Collideable::collidesWith(Collideable* c)
According to http://www.cplusplus.com/doc/tutorial/operators/ the logical operators return a boolean value (which makes sense to me, coming from Java) so what's causing this problem?
It is difficult to know if this is what is in the program or a simple transcription problem:
The first line is written ending as c-getMaxX(); maybe it should be c->getMaxX()?
You have c-getMaxX() but you need c->getMaxX(), with a >.
I'm making an input range to iterate over a custom container that holds data points that need to remain accurately paired as inputs and targets. I need different Ranges for returning training data (double[][]), inputs (double[]) and the targets (also double[]). I managed to get the following code to compile and work perfectly, but I don't know why.
public struct DataRange(string type)
if( type == "TrainingData" ||
type == "InputData" ||
type == "TargetData" )
{
private immutable(int) length;
private uint next;
private Data data;
this(Data d){
this.length = d.numPoints;
this.next = 0;
this.data = d;
}
#property bool empty(){return next == length;}
#property auto front(){
static if(type == "TrainingData")
return this.data.getTrainingData(next);
else static if(type == "InputData")
return this.data.getInputData(next);
else return this.data.getTargetData(next);
}
void popFront(){++next;}
}
static assert(isInputRange!(DataRange!"TrainingData"));
static assert(isInputRange!(DataRange!"InputData"));
static assert(isInputRange!(DataRange!"TargetData"));
I've been reading the "The D Programming Language" by Alexandrescu, and I have found parameterized structs of the form
struct S(T){...} // or
struct S(T[]){...}
but these take type parameters, not expressions like I've done. I haven't been able to find any similar examples on dlang.org with parameterized types.
This compiles and works on DMD 2.066 and GDC 4.9.0.
I don't even know why I tried this, and looking back at it I don't know why it works. Anybody know what I'm missing? Where is this documented?
Ok, I found the answer. Though this wasn't specifically mentioned or described in any of the tutorials or anywhere in the book, I was eventually able to find it at http://dlang.org.template.html. Basically there are two things going on here.
1.) Though my code says struct, this is really a template (that results in a struct). I have seen examples of this online and in the book, though it wasn't described as a template. It was a bit confusing because I didn't use the template keyword, and in the book they are described as "parameterized."
2.) From the website linked above...
Template parameters can be types, values, symbols, or tuples
So in my case my template parameter was a symbol. The examples in the book used types.
Digging into the language specifications on the website reveals there is a lot more going on than is covered in the book!
Alternatively you could use an enum to simplify the constraint in such a way that a wrong template instantiation is impossible (even if in your code the template constraint does it perfectly). example:
enum rangeKind{training, input, target};
public struct DataRange(rangeKind Kind)
{
}
void main(string args[])
{
DataRange!(rangeKind.training) dr;
}
I've been messing around with C++ SDL for a few days now and I've come across an interesting problem.
SDL_Event event1;
while(SDL_WaitEvent(&event1))
{
for(size_t i = 0; i < MainMenuOptions.size();i++)
{
if(event1.button.x > MainMenuOptions.at(i).GetX() && event1.button.x < (MainMenuOptions.at(i).GetX() + MainMenuOptions.at(i).GetWidth())
&& event1.button.y > MainMenuOptions.at(i).GetY() && event1.button.y < (MainMenuOptions.at(i).GetY() + MainMenuOptions.at(i).GetHeight()))
{
break;
}
}
}
When I use break in the for loop its going to break out of the for loop instead of the while loop. How would I break out the while loop instead without using the goto statement? (the goto statement is bad programming, I heard)
The common solution is to put this stuff into its own function and return from that:
inline SDL_Event do_it()
{
SDL_Event event;
while(SDL_WaitEvent(&event))
for(std::size_t i = 0; i < MainMenuOptions.size(); ++i)
if(/*...*/)
return event;
return event; // or whatever else suits, I know too little about your code
}
There's another answer to that, and I think I should say it before everyone will downvote me.
Using a variable is certainly a "good" way to do it. However, the creating additional variable just to jump out of the loop seems a bit of overkill, right?
So yes, this time goto is perfect solution. It's perfectly clear what you are doing with it, you are not using another variable and the code remains short, maintainable and readable.
The statement goto is bad practice is mostly a remnant of the BASIC times, when it was quite the only way of changing code flow. However, now we "know better", and saying that the goto or any other construction is bad, just doesn't cut it. It can be bad for one particular problem you are trying to solve with it (and it's the case with most of the problems that people try to solve with goto). However, given the right circumstances (like here) it's OK. I don't want to start a debate here, of course. Goto is like a very powerful tool (sledgehammer, for example). It has its uses and you can't say a tool is totally bad; it's the user using it in the wrong way.
Use a variable to indicate the need to exit:
bool exit_program = false;
while( !exit_program && SDL_WaitEvent(&event1) )
{
for( /* ... */ )
{
exit_program = true;
}
}
First point: IMO, you're trying to wrap too much up into a single place, and ending up with something that's fairly difficult to understand -- somebody has to read through that entire long set of comparisons before they can understand any of what this is supposed to accomplish at all.
Second point: using an explicit loop to iterate over a standard collection is usually a mistake -- and this is no exception. The standard library already has an algorithm to accomplish the same basic thing as your loop. It's better to use that than write it again yourself.
template <class T>
bool in_range(T a, T b, T c) {
return (a > b) && (a < b+c);
}
class in_rect {
point p;
public:
in_rect(point const &p) : p(p) {}
// Not sure of the type of objects in MainMenuOptions, so just T for now.
//
bool operator()(T const &m) {
return in_range(p.x, m.GetX(), m.GetWidth())
&& in_range(p.y, m.GetY(), m.GetHeight());
}
};
SDL_Event event1;
while (SDL_WaitEvent(&event1))
if (std::any_of(MainMenuOptions.begin(), MainMenuOptions.end(),
in_rect(event1.button))
break;
Once we fix the other problems, there's simply no longer any need (or even use) for the goto. We haven't taken any steps explicitly intended to remove it, but when the other problems have been fixed (especially, replacing the loop with an appropriate algorithm), the use for it has disappeared.
I suppose I should preemptively comment on the increase in the total number of lines of code: yes, there are more lines of code. What of it? If we really wanted to, we could use the same basic approach, but instead of defining in_rect and in_range, we'd basically just take the condition from the original if statement and stuff it into a lambda. While I'm very happy that lambdas have been added to C++, in this case I'm not excited about using it. It would get rid of the goto, but in general the code would be almost as unreadable as it started out.
Simply put, the number of lines isn't a good way to measure much of anything.
A solution without additional variable and goto:
while(SDL_WaitEvent(&event1))
{
size_t i;
for(i = 0; i < MainMenuOptions.size();i++)
{
if(/* ... */)
{
break;
}
}
if (i < MainMenuOptions.size())
break;
}
I am implementing libxmlrpc into C++ project, anywayy, my RPC server has returned a struct with 52 member structs in them.
I do not know what the keys are as they are opaque references, so I cannot rely on them.
How can I iterate through the struct, I would have thought it was with the following code:
XmlRpcValue param_array = XmlRpcValue::makeArray();
param_array.arrayAppendItem(XmlRpcValue::makeString(this->sessionKey));
param_array.arrayAppendItem(XmlRpcValue::makeString("petabytes"));
XmlRpcValue result = ServerCall("Charter.getDataWarehouse.storage.capacity", param_array, url);
int index = 0;
while(index < result.structSize())
{
XmlRpcValue Data = result.getStruct();
//Would have thought it would work with this ;( shit documentation libxmlrpc has, grrrr
//Data.structGetKeyAndValue(index);
//This for example works, because I know the opaque reference, but in real life I wont
cout << Data.structGetValue("OpaqueRef:d4e60db6-2271-b0ac-d362-1b51220980af").structSize() << endl;
index++;
}
However, Data.structGetKeyAndValue(index) errors with:
no matching function for call to 'XmlRpcValue::structGetKeyAndValue(int&)
Which is fine, I understand it's not a public (well I think it's not a public member function) of xmlrpcvalue, however I cannot find anything that would allow me to do this.
Anyone have any experience with this?
Some quick Googling seems to indicate that you've got the function signature wrong:
void XmlRpcValue::structGetKeyAndValue(const int index, std::string& out_key, XmlRpcValue& out_value);