C++ casting operators

Today in my research, I came across an interesting challenge. I’m editing an older version of JavaScriptCore (JSC), redefining the most basic typedef in the sytem, EncodedJSValue. Previously it was a simple void*, but I need to gift it with some special secret sauce, so I changed it to a struct.

typedef struct EncodedJSValue {
    void *value;
 
    // additional functionality elided
}

Most of the additional functionality could be filled in by following compiler errors. But one error deep in the system took some special cleverness. My initial (and failing) attempts at fixing the issue led me into a strange corner of the C++: overloading of the cast operators.

g++’s error messages are confusing, so I originally (wrongly) thought that the EncodedJSValue‘s were sometimes used to hold function pointers. Specifically typedef int(*jitStub)(void**); So, how to convert an EncodedJSValue to a function pointer?

Well, I know from online reading, that it’s possible to implement an operator that can convert from EncodedJSValue to int.

typedef struct EncodedJSValue {
    void *value;
 
    operator int() {
        return static_cast<int>(value);
    }
}

So what would be the syntax for writing a typecast operator from EncodedJSValue to a function pointer? Although I know the syntax for function pointers (see the jitStub typedef previously), I was pretty sure that I could not just paste that into the operator definition. Besides that, function pointers don’t read very nicely, and keeping a typedef around helps the code to be more self-explanatory. So, I tried making an operator jitStub, and it worked. No complaints from the compiler!

typedef int(*jitStub)(void**);
 
typedef struct EncodedJSValue {
    void *value;
 
    operator jitStub() {
        return static_cast<jitStub>(value);
    }
}

Also, I found out by writing a separate test, the conversion can be called implicitly.

EncodedJSValue jsv;
void **arg;
 
int x = jsv(jitStub);

Although this didn’t solve my compilation problem, I did learn another dark corner of the labyrinthine C++. Using the much better error reporting in clang helped me to interpret my actual problem.