I'm writing a C wrapper and I have an enum:

enum SANE_Status
{
    SANE_STATUS_GOOD = 0,     /* everything A-OK */
    SANE_STATUS_UNSUPPORTED,  /* operation is not supported */
    SANE_STATUS_CANCELLED,    /* operation was cancelled */
    ...
}

Now, what I really hate to see is this:

if ( status == SANE_Status.SANE_STATUS_GOOD )
    doSomething();

This is incompatible with how the C code would be written. Even worse: so much repetitive noise! It gets worse yet when the enum members are arguments to functions and there are more than one of them.

I understand that I could also write code this way:

alias int SANE_Status;
enum : SANE_Status
{
    SANE_STATUS_GOOD = 0,     /* everything A-OK */
    SANE_STATUS_UNSUPPORTED,  /* operation is not supported */
    SANE_STATUS_CANCELLED,    /* operation was cancelled */
    ...
}

This gives a more C-like behavior. However, I no longer have an enum type that is distinct from 'int' and, more importantly, I can't use "final switch(status) {...}" on this because typeof(status) isn't an enum. It still allows me to write the final switch without compiler errors, but it won't enforce exhaustiveness.

I am having some luck with this:

--------------------------
enum SANE_Status
{
    SANE_STATUS_GOOD = 0,       /* everything A-OK */
    SANE_STATUS_UNSUPPORTED,    /* operation is not supported */
    SANE_STATUS_CANCELLED,      /* operation was cancelled */
    SANE_STATUS_DEVICE_BUSY,    /* device is busy; try again later */
SANE_STATUS_INVAL, /* data is invalid (includes no dev at open) */
    SANE_STATUS_EOF,            /* no more data available (end-of-file) */
    SANE_STATUS_JAMMED,         /* document feeder jammed */
    SANE_STATUS_NO_DOCS,        /* document feeder out of documents */
    SANE_STATUS_COVER_OPEN,     /* scanner cover is open */
    SANE_STATUS_IO_ERROR,       /* error during device I/O */
    SANE_STATUS_NO_MEM,         /* out of memory */
    SANE_STATUS_ACCESS_DENIED   /* access to resource has been denied */
}

alias SANE_Status.SANE_STATUS_GOOD SANE_STATUS_GOOD;
alias SANE_Status.SANE_STATUS_UNSUPPORTED SANE_STATUS_UNSUPPORTED;
alias SANE_Status.SANE_STATUS_CANCELLED SANE_STATUS_CANCELLED;
alias SANE_Status.SANE_STATUS_DEVICE_BUSY SANE_STATUS_DEVICE_BUSY;
alias SANE_Status.SANE_STATUS_INVAL SANE_STATUS_INVAL;
alias SANE_Status.SANE_STATUS_EOF SANE_STATUS_EOF;
alias SANE_Status.SANE_STATUS_JAMMED SANE_STATUS_JAMMED;
alias SANE_Status.SANE_STATUS_NO_DOCS SANE_STATUS_NO_DOCS;
alias SANE_Status.SANE_STATUS_COVER_OPEN SANE_STATUS_COVER_OPEN;
alias SANE_Status.SANE_STATUS_IO_ERROR SANE_STATUS_IO_ERROR;
alias SANE_Status.SANE_STATUS_NO_MEM SANE_STATUS_NO_MEM;
alias SANE_Status.SANE_STATUS_ACCESS_DENIED SANE_STATUS_ACCESS_DENIED;


void foo(SANE_Status s)
{
    final switch(s)
    {
        case SANE_STATUS_GOOD: writeln("Good!"); break;
case SANE_STATUS_UNSUPPORTED: writeln("operation is not supported"); break; case SANE_STATUS_CANCELLED: writeln("operation was cancelled"); break; case SANE_STATUS_DEVICE_BUSY: writeln("device is busy; try again later"); break; case SANE_STATUS_INVAL: writeln("data is invalid (includes no dev at open)"); break; case SANE_STATUS_EOF: writeln("no more data available (end-of-file)"); break;
        case SANE_STATUS_JAMMED: writeln("document feeder jammed"); break;
case SANE_STATUS_NO_DOCS: writeln("document feeder out of documents"); break; case SANE_STATUS_COVER_OPEN: writeln("scanner cover is open"); break; case SANE_STATUS_IO_ERROR: writeln("error during device I/O"); break;
        case SANE_STATUS_NO_MEM: writeln("out of memory"); break;
case SANE_STATUS_ACCESS_DENIED: writeln("access to resource has been denied"); break;
    }

    writeln("foo works.");
}

int main(string[] args)
{
    SANE_Status s = SANE_STATUS_GOOD;
    if ( s == SANE_STATUS_GOOD )
        writeln("hi!");

    foo(SANE_STATUS_GOOD);

    return 0;
}

--------------------------

But I would probably need some nontrivial CTFE to generate the aliases.

There has to be a better way!

Please help.

Reply via email to