You don’t see me calling Linux users tux turds, penguin poopers or GUI-challenged, do you?
http://www.pcmech.com/article/good-linux-users-dont-talk-about-microsoft/
Enjoy
You don’t see me calling Linux users tux turds, penguin poopers or GUI-challenged, do you?
No preprocesor wizard should go out of his house without the always useful string maker. Let's say you're trying to create a class with some sort of pseudo type-system (*):
class FooBar {
public:
const char* get_name(){ return "FooBar"; }
};
Why would you type ALL that when you can make a simple macro, MK_CLASS, like this:
MK_CLASS( FooBar )
/* Other methods */
};
Problem is, this will only print "Name":
#define MK_CLASS( Name )
class Name { public:
const char *get_name(){ return "Name"; }
Well, it's an easy fix, just prepend # to your string, like this:
#define MK_CLASS( Name )
class Name { public:
const char *get_name(){ return #Name; }
Or use this nice string maker:
#define MK_STR(str) #str
As usual, use the preprocesor at your own risk.
(*) Yeah, I know, OO purists will try to beat me to death for this, but it actually has some uses. I've found it to be a specially good solution when working with low level protocols.
I get it, C++ is a complex language, but man, I'd like a little warning (lol) when this happens:
class Foo {
int bar;
Foo() : bar(bar) {}
};
Yeah, it bit me in the ass the other day. Why? A method's signature was awfully long, I wanted to delete a parameter and ended up deleting two. Luckly my unit tests where there to save the day, but regardless, WTF?
There's nothing better than feeling like a super villain by having a dual monitor setup. OK, three may be better, you probably couldn't hold back the evil laughter, but my laptop won't support three screens.
Fortunately, in Ubuntu JJ having a dual screen setup is a breeze. Just plug the two monitors and hope it works. Of course, it may not. If that's the case you can go to System > Preferences > Screen for a nice GUI, which will let you select each screen's resolution and position. Nothing better for productivity than having your monitors swapped, or even better, flipped upside down.
Well, sometimes "Screen Preferences" won't work either, too bad. In that' case you'll have to get dirty with xrandr. It's not too difficult but it's console based (you're not scared of the console, are you?).
Though the man page for xrandr is a little bit intimidating at first you'll just have to do it once, so I won't write about using it, I will just copy & paste a script I keep in my desktop to fix the screen whenever it brakes (my lapop tends to foobar my screen when being docked or undocked, not sure why)
xrandr --output HDMI-2 --right-of HDMI-1 --mode 1680x1050 --rotate normal
I am sure you can figure out the rest on your own - enjoy the dual screen setup!
Although I'm quite happy with Ubuntu 9.04, I find a couple of new features quite annoying. The warning message it pops up whenever you try to close a console with a running program in it falls in this category. Fortunately it's not difficult to disable:
All set. As a bonus side effect now closing a terminal with multiple tabs won't pop up a message either.
Long post this time - and lots of code too. How fun iz that? Anyway, remember where we left last time? We're supposed to make this work:
class Callee {
Callback notify;
public:
Callee(Callback notify) : notify(notify) {}
void finish(){ notify(this); }
};
class Caller {
Callee c;
public:
Caller() : c(Callback(this, &Caller::im_done)) {}
void im_done(Callee*) { }
};
I'll write about the different solutions I've tried and the problem each of these solutions had:
We could to this the easy way, with a template:
template <class Callback>
class Callee {
...
};
class Caller {
template <class T>
void operator() (T p){ this->im_done(p); }
...
};
This has some drawbacks:
So, lets try another approach: the naive one is an interface:
class iCallback {
public:
template <class T> void operator () (T o) = 0;
};
Looks great, doesn't it? Too bad it's not valid C++, you can't have a virtual template method (what would the vtable size be?).
If we can't have a template method let's make a template class:
template <class T>
class iCallback {
public:
virtual void operator () (T o) = 0;
};
class Callee {
iCallback<Callee*> *notify;
public:
Callee(iCallback<Callee*> *notify) : notify(notify) {}
void finish(){ (*notify)(this); }
};
class Caller : public iCallback<Callee*> {
Callee c;
public:
Caller() : c(this) {}
void im_done(Callee*) {}
void operator ()(Callee *o){ im_done(o); }
};
It may not be pretty but it works. Also, adding a callback means adding a new operator (). Lets try to improve it a little by removing the nasty inheritance (remember, always prefer composition over inheritance):
template <class P>
class iCallback {
public:
void operator () (P o) = 0;
};
template <class T, class P>
class Callback : public iCallback<P> {
// Notice this typedef: we have an object of type T and a
// function accepting a parameter P
typedef void (T::*member_func) (P);
T *cb_obj; member_func f;
public:
Callback(T* cb_obj, member_func f)
: cb_obj(cb_obj), f(f) {}
inline void operator() (P o){
(cb_obj->*f)(o); // ->* is the best voodoo operator
}
};
This new object should help us to:
How would this change leave our code?
class Caller;
class Callee {
Callback<Caller, Callee*> *notify;
public:
Callee(Callback<Caller, Callee*> *notify) : notify(notify) {}
void finish(){ (*notify)(this); }
};
class Caller {
Callback<Caller, Callee*> cb;
Callee c;
public:
Caller() : cb(this, &Caller::im_done), c(&cb){}
void im_done(Callee*) {}
};
Oops, looks like we took one step back: now Callee MUST know the type of Caller. Not nice. Luckily it is an easy fix:
class Callee {
iCallback<Callee*> *notify;
public:
Callee(iCallback<Callee*> *notify) : notify(notify) {}
void finish(){ (*notify)(this); }
};
OK, we're back on track. We will solve that weird looking (*notify)(this) later, don't worry.
We're almost there, but specifying the callback as Now we no longer need to specify the Caller type. There's still a nasty issue about pointer-vs-object passing. Using (*notify)(this) is very ugly so let's do it like this:
Nice, this time it should work as expected. Only it does not, there is something horribly wrong about it. Can you see what it is? Take a second, I'll wait... OK, back? Right, it segfaults! Why? Easy, take a look at this:
We are using a copy constructor here, and what does our wrapper store?
Indeed, the copied WrapperCallback ends up pointing to a deleted Callback when the cb field of the original object gets copied and then destructed. We should have all the pieces to fix it now: we just need to implement the copy operator to make it work. How does the final version looks like?
Now we have a nice callback object which can link two objects without them knowing each other. There is room for future improvement, of course:
template <class R>
class WraperCallback {
iCallback<R> *cb;
public:
template <class T, class F>
WraperCallback(T* cb_obj, F f)
: cb( new Callback<T, R>(cb_obj, f) ) {}
~WraperCallback() {
delete cb;
}
inline void operator()(R o){
(*cb)(o);
}
};
Experiment 5: Callback object bis
class Callee {
WraperCallback<Callee*> notify;
public:
Callee(WraperCallback<Callee*> notify) : notify(notify) {}
void finish(){ notify(this); }
};
class Caller {
Callee c;
public:
Caller() : c(WraperCallback<Callee*>(this, &Caller::im_done)) {}
void do_it(){ c.finish(); }
void im_done(Callee*) { }
};
Callee(Callback<Callee*> notify) : notify(notify) {}
WraperCallback(T* cb_obj, F f)
: cb( new Callback<T, R>(cb_obj, f) ) {}
Solution
template <class P> class iCallback {
public:
virtual void operator()(P) = 0;
virtual iCallback<P>* clone() const = 0;
};
template <class T, class P>
class RealCallback : public iCallback<P> {
typedef void (T::*member_func) (P);
T *cb_obj; member_func f;
public:
RealCallback(T* cb_obj, member_func f)
: cb_obj(cb_obj), f(f) {}
/**
* The clone operator is needed for the copy ctr of
* the Callback object
*/
inline iCallback<P>* clone() const {
return new RealCallback<T, P>(cb_obj, f);
}
inline void operator() (P o){
(cb_obj->*f)(o); // ->* is the best vodoo operator
}
};
template <class R>
class Callback {
iCallback<R> *cb;
public:
template <class T, class F>
Callback(T* cb_obj, F f)
: cb( new RealCallback<T, R>(cb_obj, f) ) {}
Callback(const Callback& cpy)
: cb( cpy.cb->clone()) {}
~Callback() {
delete cb;
}
inline void operator()(R o){
(*cb)(o);
}
};
Conclusion