Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

You can use std::remove_reference (see http://en.cppreference.com/w/cpp/types/remove_reference).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top