In C++, I want to have a class whose constructors are the following:
class A {
explicit A(A* other) { ... }
explicit A(intptr_t other) { ... }
};
The problem with this is if the user initialize with
A a(0);
Then, on a 64 bits system, the compiler will complain that it doesn’t know if 0 should be converted to A* or to intptr_t, which is fair enough. As I want this simple notation to work, I added the following constructor:
explicit A(int a) { assert(a==0); ... }
The assertion is because this is the only integer this makes sense for. Now, the problem arises with a 32 bits system, in which intptr_t is actually … int ! So now, the system complains there are two constructors taking the same parameter type (which, again, is fair enough).
So my question is: is there a way with the preprocessor to detect that intptr_t is actually int and, in that case, not compile the constructor with int. Or, is there another way to make the A a(0) notation valid without adding the constructor with int, but without removing either of the two first constructor (and not making them implicit either).
Something like
might do the trick, but it will still result in true where
longandintare the same size, andptrint_tis a typedef forlong.Another possibility (but don’t know whether you can use it or not)
would be to use
uintptr_t, rather thanintptr_t.Beyond these: the preprocessor doesn’t know about types, so the problem
can’t be solved there. You’ll have to use some sort of meta-programming
trick: you make the
intconstructor a template, usingboost::enable_ifto activate it only if the argument has typeint.If
ptrint_tisint, then the activated function will never beused, because it will never be a better match than the non-template
function with the same signature. If
ptrint_tisn’tint, then thetemplate instantiation will be a better match when the argument has type
int. (Note that I’ve never tried this myself: it sounds to me like itshould be possible, but I’m not that familiar with
boost::enable_iftobe sure.)