I'm working on some code using decltype in CodeGear RAD Studio. I've tried the naive solution, which looks not unlike this:
int main(int, char**) {
int i;
int &ir = i;
decltype((ir)) ir_clone = ir;
}
Of course, this fails to compile: Internal Compiler Error. I rather suspect that there is nothing particularly wrong with that code and there is a compiler bug regarding reference expressions. (Incidentally, g++ has no problem with the code and compiles it fine.) That doesn't help solve the problem, however, as the platform is non-negotiable.
If, above, I had written
decltype(ir) ir_clone = ir; /* No extra parens */
it compiles and works as expected. However, the problem doesn't end there, since that doesn't correctly compute constness from the environment. In particular:
struct S { int i; } s;
const S* p = &s;
decltype(p->i) i0 = s.i; /* i0 is an int */
decltype((p->i)) i1 = s.i; /* i1 is a const int& */
If I don't use the parens to make the argument an expression, I lose the constness of the argument, which I need.
Another tool I can use is simple templates, like so:
template<class T> struct unref { typedef T type; }
template<class T> struct unref<T&> { typedef T type; }
That lets me strip away the reference portion of a type, by using unref<int&>::type
.
What I can't seem to figure out is how to put all these tools together to get a successful expression for the type I need. For one of things I need, I'm working on a generalized macro that does 'foreach'. (Yes, I know Boost does it better.) It needs to handle the following scenarios:
(vector<int>) vi => vector<int>
(vector<int>&)vir => vector<int>
(const vector<int>) cvi => const vector<int>
(const vector<int>&)cvir => const vector<int>
(const P*) cp->vi => const vector<int>
(P*) p->vi => vector<int>
So far, my simple attempts fail:
unref<decltype(cp->vi)> /* is vector<int>, not what I need. */
unref<decltype((cp->vi))> /* is const vector<int>, which is right. */
unref<decltype(vir)> /* is vector<int>, which is right. */
unref<decltype((vir))> /* Internal Compiler Error, which is a headache. */
Any ideas to get me on the right track? Hopefully there's just something simple I'm missing. Maybe I'm attacking the problem from the wrong angle.
Try making a different, more complex expression that results in the same type that you want, such as:
decltype((void(), ir))
I couldn't tell you why it fixes it, but sometimes a different expression will do the trick.