[cairo] Re: cairo c++ bindings
Marco Manfredini
mldb at gmx.net
Fri Dec 2 03:19:58 PST 2005
On Monday 28 November 2005 21:53, Bill Spitzak wrote:
> Murray Cumming wrote:
> > An if(somebool) will not add a significatn amount of run-time overhead.
> > I'd be happy to add a Cairo::set_ignore_errors(bool) function.
> Actually it will if the code is inlined, as it can add significant size
> to the code and thus make things not fit in caches. A quick test reveals
> that this triples the size of the inlined code (for a phony test with
> one argument passed to the other function).
This is exactly what I've observed when writing wrappers, and there is another
point that hasn't been discussed with the idea of "policies": How do I assign
precise throw() specifications to the members? Being able to assert what a
function throws makes a good argument to code review and literally pays out
when the compiler sees that it can remove clean up frames from the code.
> My preference would be for the C++ wrapper to not test anything or throw
> any exceptions, and to just wrap the "test status" call like every other
> Cairo interface. Calling code can do "if (cairo_c->error()) throw
> exception;"
>
> The ideas mentioned below for using templates to make a different class
> that does throw exceptions may be a good idea, though, as long as the
> header files are still readable.
I don't event think that there is a need to deal with exceptions at all
(except for the requirement that the wrappers are exception safe), because an
user defined exception policy can easily be defined externally using a proxy
class:
void drawSomething(Context _c) // Context does not care for status
{
guarded<Context> c(_c);
c->moveTo(0,0);
c->lineTo(10,10); // every call is status checked and throws if neccesary.
...
}
To illustrate this, here's a rought sketch of guarded:
// this needs some polishing to handle const and reference parameters:
template<class T>
struct guarded
{
private:
struct proxy
{
T &t;
inline proxy(T &_t) throw() : t(_t) {}
inline T * operator -> () throw() { return & t; }
inline ~proxy() throw(Status)
{
Status s=t.status();
if (s != STATUS_SUCCESS)
{
throw s;
}
}
};
T object;
public:
inline guarded(T obj) throw() : object(obj) {}
// operator -> cascading
inline proxy operator -> () throw() { return object; }
inline operator T & () const throw() { return object; }
};
This looks like overhead, but the essentially the optimizer will remove the
creation of the proxy alltogether and just leave the check from ~proxy.
Marco
More information about the cairo
mailing list