开发者

c++ casting a union to one of its member types

开发者 https://www.devze.com 2023-02-12 09:43 出处:网络
The following seems perfectly logical to me, but isn\'t valid c++. A union cannot be implicitly cast to one of it\'s member types. Anyone kno开发者_开发百科w a good reason why not?

The following seems perfectly logical to me, but isn't valid c++. A union cannot be implicitly cast to one of it's member types. Anyone kno开发者_开发百科w a good reason why not?

union u {
  int i;
  char c;
}
function f(int i) {
}
int main() {
  u v;
  v.i = 6;
  f(v);
}

And can anyone suggest a clean alternative (the cleanest I can come up with is f(v.i);, which I admit is very clean, but the above just seems even cleaner)


While agreeing with Crazy Eddie that it doesn't look that better to me you can actually get an implicit conversion by defining it:

union u {
    int i;
    char c;
    operator int () const { return i; }
    operator char () const { return c; }
};


The reason why this isn't available implicitly (by default) is that it can be ambiguous. It's completely legal to have more than one member with the same type, and there would be no reason to prefer one or the other.

union u
{
    char c;
    TCHAR t;
    wchar_t w;
    int i;
};
void f(TCHAR);

u v;
f(v); // which member should be used?


How would the compiler know which member to use? It would need to keep track of which member was last assigned so it knows what to convert to. This is called a tagged union, and while it's certainly possible for the language to specify such a thing, that's not the case (it's a hold-over from C).

But that's okay, because we have boost::variant. Not only is it safer and more flexible than a union, it's more powerful. You can apply visitors to the variant, and it'll call (visit) the specified function with whichever member is currently active, with no further work from the user.


There is no different syntax I am familiar with. To be honest, accessing the union member directly is rather clear and concise as is.

I assume the reason there is no implicit casting is because of some rule whereby it's technically "undefined behavior" to write to one member of a union, then read from another member.

The implicitly casted type may not be the last one written to. While it's perfectly compilable code and it would probably work fine, the compiler, in principle, should not automatically or implicitly do something that is against the very rules it enforces.


Anyone know a good reason why not?

function f(char c) {
    doStuff(c);
}

Best reason I can think of.

And can anyone suggest a clean alternative?

I'm with Crazy Eddie on this one; f(v.i) is as "clean" as it gets without inviting programmer errors. Two extra characters is an acceptable price to pay for more robust code, no?

0

精彩评论

暂无评论...
验证码 换一张
取 消