Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
oldkike
Jan 10, 2003

hey

www.pleasegimmeadollar.com
I was trying to do a easy-to-use observer pattern in C++. I'm kind of new to it.

code:
#include <algorithm>
#include <functional>
#include <list>

using namespace std;

class Subject;

class Observer
{
   public:
      virtual void call(Subject *s) = 0;
};

template<class T>
class CbObserver : public Observer
{
public:
  CbObserver(void (T::*f)(Subject *), T *o) : mF(f), mO(o) {}
  void call(Subject *s) { ((mO).*(mF))(s); }
private:
  void (T::*mF)(Subject *);
  T* mO;
};

class Subject
{
public:
   void notify() {
      for(list<Observer *>::iterator i = mObservers.begin();
          i != mObservers.end();
          i++)
      {
          (*i)->call(this);
      }
   }
  void addObserver(Observer *o) { mObservers.push_back(o); }
private:
   list<Observer *> mObservers;
};

Is there any way to do this without having to do a "new" for every observer? Ideally I'd like for the Subject to be observed by multiple classes with multiple methods in each class..

Adbot
ADBOT LOVES YOU

oldkike
Jan 10, 2003

hey

www.pleasegimmeadollar.com

cronio posted:

If you want a more generic solution, check out http://nocturnal.insomniacgames.com/index.php/Common#Automation.2FEvent.h

It's part of our new opensource initiative, Nocturnal. You can download the code from http://nocturnal.insomniacgames.com/releases/Common/

Other options include FastDelegate (which ours is based on) -- http://www.codeproject.com/KB/cpp/FastDelegate.aspx, and boost::bind.

If you want a really generic solution, check out libsigc++. It supports multiple args to callbacks all with type-safety.

oldkike
Jan 10, 2003

hey

www.pleasegimmeadollar.com

cronio posted:

How is this more generic than FastDelegate? (I don't know much about boost::bind, so I won't ask about it)

The support for Rebinding/Retyping doesn't seem compelling to me, since I prefer callbacks to be single-purpose (if the code needs to happen from multiple execution paths, I'd prefer the callback(s) call another function that does the work, rather than have a single callback that is rebinded/retyped).

Marshalling seems like it could be useful, but I can't think of any time I've actually needed that functionality.

Anyway, I'm not trying to knock libsigc++, I'm genuinely curious.

I was referring to the first link. The FastDelegate link was broken, but I googled it and saw that it was pretty equivalent to libsigc++. One nice thing about libsigc++ is that GTK uses it, so if you're using it in the application you can tie the GUI to everything without adapters and wrappers..

oldkike
Jan 10, 2003

hey

www.pleasegimmeadollar.com

cronio posted:

It's reasonable. If your files aren't going to be large though (if you're on a PC, on the order of tens of megabytes), reading the entire file and doing all the parsing in-memory is actually a better (faster) solution.

I'm used to C++, so this may not be perfectly valid C (variable declarations need to go to the top of the function for example).

code:
fseek( f, 0, SEEK_END );
int fileSize = ftell( f );
fseek( f, 0, SEEK_SET );

char* buf = (char*)malloc(fileSize);
fread( buf, 1, fileSize, f );

... parse ...

free( buf );
[edit] As far as string parsing goes in C, it basically sucks. atoi/atof/etc. are your friends, just make sure your strings are NULL terminated. The sn_ functions (snprintf, snscanf, etc.) are also handy (if your compiler supports them -- I'm not sure if they're standardized or not), since they take the size of the buffer, and so won't ever read off the end.

atoi, atof, etc are deprecated. Look at strtol, strtod, etc.

oldkike
Jan 10, 2003

hey

www.pleasegimmeadollar.com
C and C++ are so weird sometimes. Here's another syntax weirdness:

Valid C++:
code:
int main(int argc, char **argv)
try
{
  std::cout << "hello world" << endl;
} catch (...) {
  std::cout << "..." << endl;
}
Edit: Another, this evaluates differently in C and C++

code:
printf("%d\n",sizeof 1 ? "ab" : "cd");

oldkike fucked around with this message at 05:54 on Mar 3, 2008

oldkike
Jan 10, 2003

hey

www.pleasegimmeadollar.com

FearIt posted:

This is the function I'm using to simulate the mouse, the problem is some mouseclicks aren't being registered in the program I'm clicking over, even though the mouse cursor will move to the correct spot.

I've tried using sleep statements between the mouseclicks but that has been for the most part unsuccessfull. What can I do to make sure the mouse is being simulated?

code:
void IO::mouseClick(int x, int y)
{
	INPUT *buffer = new INPUT[3]; //allocate a buffer

	(buffer+1)->type = INPUT_MOUSE;
	(buffer+1)->mi.dx = 100;
	(buffer+1)->mi.dy = 100;
	(buffer+1)->mi.mouseData = 0;
	(buffer+1)->mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
	(buffer+1)->mi.time = 0;
	(buffer+1)->mi.dwExtraInfo = 0;

	(buffer+2)->type = INPUT_MOUSE;
	(buffer+2)->mi.dx = 100;
	(buffer+2)->mi.dy = 100;
	(buffer+2)->mi.mouseData = 0;
	(buffer+2)->mi.dwFlags = MOUSEEVENTF_LEFTUP;
	(buffer+2)->mi.time = 0;
	(buffer+2)->mi.dwExtraInfo = 0;
	SetCursorPos(x,y);

	if(::GetAsyncKeyState(VK_LCONTROL) > 0){
		while(SendInput(3,buffer,sizeof(INPUT)) == 0){::Sleep(50);}
	}

	delete (buffer); //clean up our messes.
}


You're trying to send all 3, and if it fails (and only sends one), you try to send all 3 again. I'm guessing its probably only ever getting the mouse down event. Also, why do you use this weird pointer addition thing instead of buffer[i].attribute.etc

oldkike
Jan 10, 2003

hey

www.pleasegimmeadollar.com

JoeNotCharles posted:

Argh, binary shifting! Pitfalls!

code:
unsigned short value = 0L;
char ch = blah blah blah
value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
That's giving me a warning because it converts ch to a long and then truncates it to a short. If I just change that to "(unsigned short) ch", will that cause any side effects? (Like << and >> automatically extending, or something?)

You shouldn't need to cast that at all.. I don't think that case affects the shift at all, because its adding *after* the shift.

oldkike
Jan 10, 2003

hey

www.pleasegimmeadollar.com

ultra-inquisitor posted:

I've heard that the best way to implement variadic functions is to overload the << operator. Is this true, and what's the most efficient way of doing this? I can't think of how it would be done.

Never heard of this. But this is what I would imagine:

code:

class Arg
{
...
};

class EndArgs {};

class Args
{
public:
 Args(Functor f) : mFunctor(f) { }
 Functor<void,std::list<Arg>> f;
 std::list<Arg> args;
};

Args& operator<<(Args& args, const Arg& arg)
{
 args.args.push(arg);
}

Args& operator<<(Args &args, const EndArgs&)
{
 args.f(args.args);
 args.args.clear();
}

usage:

void my_function(std::list<Arg>) { ... }

Functor<void,std::list<Arg>> my_functor(my_function);
Args my_args(my_functor);

my_args << Arg(1) << Arg("blah") << Arg(...) << EndArgs;

oldkike
Jan 10, 2003

hey

www.pleasegimmeadollar.com

Super Dude posted:

I probably should have explained a little bit better. (I'm using C, so I don't think I can use boost)

Say I have the number

01011001 10100011

and I want to get the value for the range in bold (the value 6).


You need to shift it right by 10 bits, and then mask off the part you want:

code:
short your_number = 0x59a3;
int six = (your_number >> 10) & 0x7;

oldkike
Jan 10, 2003

hey

www.pleasegimmeadollar.com

Vandorin posted:

I've got a question about making your own class. I know I need a header file, and a .cpp file, and I have written both of those out, what I was wondering was, do I put the main part of the program in the same .cpp file or do I just go to add->new etc, and insert the code for the main part of my program there?

The most commonly used pattern I've seen is adding a main.cpp to the project with nothing more than a main function.

oldkike
Jan 10, 2003

hey

www.pleasegimmeadollar.com
I felt like I knew most of C++, until I discovered this perfectly valid C++ the other day (related to the throw stuff above).

code:
struct A {
A(int f) try : mF(f > 0 ? f : throw exception()) {} catch (...) { throw; }
};

oldkike
Jan 10, 2003

hey

www.pleasegimmeadollar.com

HondaCivet posted:

I read about "select" a bit, not sure if it's what I'm thinking of . . . I guess it isn't really a socket-related question on second thought, I just want something that can check for input without freezing up a loop.

Seems to me that calling cin.peek() would work.

Adbot
ADBOT LOVES YOU

oldkike
Jan 10, 2003

hey

www.pleasegimmeadollar.com
True ANSI C shouldn't assume the signedness of char, so if the caller expects you to use a number between 1 and 255, they should have specified "unsigned char" in the function prototype.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply