Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

MSVC++ anonymous union in struct -- compile-time initialization of non-first member

132 views
Skip to first unread message

Rick C. Hodgin

unread,
Aug 29, 2014, 9:24:54 AM8/29/14
to
Is there a compile-time workaround for this in MSVC++? Currently I am using GCC through MinGW in Windows to compile the area of the program where I need this ability, and then linking them together. But, I'd rather figure out some way to do it in a single toolset.

struct SExample
{
int x;
union {
int i;
float f;
double d;
};
};

SExample gList[] =
{
{ 0, (int)1 },
{ 1, (float)1.0f }, // Warning (1)
{ 2, (double)2.0 } // Warning (2)
};

(1) warning C4244: 'initializing' : conversion from 'float' to 'int', possible loss of data
(2) warning C4244: 'initializing' : conversion from 'double' to 'int', possible loss of data

----------
In GCC there's an extension, { 1, {.f = 1.0f} }, { 2, {.d = 2.0 } }, which I believe comes forward from C and is supported in C++ through the GCC extensions (or possibly C11??).

Is there a compile-time workaround in MSVC++? Specifically, I'm using the MSVC++ tools that came with Visual Studio 2003 and Visual Studio 2008.

My MSVC++ workaround today is a run-time initialization. I initialize them to integer values (the first union member) in source code, and then in my custom init() code I manually populate those entries with their proper float and double values. The actual source code this example relates to is much longer and I have several that need updated. I'd rather figure out a way to do it entirely at compile time, and in the single MSVC++ toolset.

Thank you in advance for any assistance.

Best regards,
Rick C. Hodgin

Victor Bazarov

unread,
Aug 29, 2014, 9:39:08 AM8/29/14
to
The Standard doesn't allow that, AFAIK. See 8.5.1/15.

If you need to learn about a possible extension in VC++, you will most
likely find help in their online forums, see msdn.microsoft.com or some
such.

V
--
I do not respond to top-posted replies, please don't ask

Rick C. Hodgin

unread,
Aug 29, 2014, 10:53:07 AM8/29/14
to
On Friday, August 29, 2014 9:39:08 AM UTC-4, Victor Bazarov wrote:
> The Standard doesn't allow that, AFAIK. See 8.5.1/15.
>
> If you need to learn about a possible extension in VC++, you will most
> likely find help in their online forums, see msdn.microsoft.com or some
> such.
>
> V
> --
> I do not respond to top-posted replies, please don't ask


Does anyone know why the C++ designers prohibited this type of compile-time
initialization at any point? It rather significantly hobbles the general
use of unions, doesn't it? Limits their full functionality solely to
run-time code.

Wait... Wait just a moment... Is that why they did it? Was this a political
movement? A battle? A rift among the ones with the pen and those actually
down in the trenches? :-) Well my my.

"Alex, I'll take 'Preplexing Standards Decision' for $1,000, please."
"Why it's the Daily Double! How much will you wager, Mr. Coder?"
"I'll wager ... $3500, Alex."
"The brace-enclosed compile-time initialization of these were hobbled
severely in C++ without dipping into implementation-specific extensions."
"What are unions?"
"Correct! And with that you now move into first place. Unless, of course,
you actually need the general use of compile-time initialization in unions,
in which case you move to last place."
"Yes. Sad, isn't it, Alex?"
"It sure is, Mr. Coder. Pathetic actually."
"I agree."
"And so do I."
"Thank you."
"And you as well."
"Oohh... these are fun times I must say."
"We'll cherish them forever."
"Indeed we will."

[pause]

"What were we doing?"
"The game show?"
"Oh yes... choose the next category."
"I'd like 'Things You Can Do With Onions' for $200."

Victor Bazarov

unread,
Aug 29, 2014, 11:19:49 AM8/29/14
to
On 8/29/2014 10:53 AM, Rick C. Hodgin wrote:
> On Friday, August 29, 2014 9:39:08 AM UTC-4, Victor Bazarov wrote:
>> The Standard doesn't allow that, AFAIK. See 8.5.1/15.
>> [..]
>
> Does anyone know why the C++ designers prohibited this type of compile-time
> initialization at any point? [..snip..]

This perhaps is better asked in comp.std.c++, the newsgroup where the
standardization process is usually discussed.

Rick C. Hodgin

unread,
Aug 29, 2014, 11:44:28 AM8/29/14
to
On Friday, August 29, 2014 11:19:49 AM UTC-4, Victor Bazarov wrote:
> On 8/29/2014 10:53 AM, Rick C. Hodgin wrote:
> > Does anyone know why the C++ designers prohibited this type of compile-time
> > initialization at any point? [..snip..]
>
> This perhaps is better asked in comp.std.c++, the newsgroup where the
> standardization process is usually discussed.


Gracias.

Ben Bacarisse

unread,
Aug 29, 2014, 2:15:50 PM8/29/14
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:

On C++ missing C's designated initialisers...

> Does anyone know why the C++ designers prohibited this type of compile-time
> initialization at any point? It rather significantly hobbles the general
> use of unions, doesn't it? Limits their full functionality solely to
> run-time code.

No, because there is a C++ way to do this: supply an overloaded
constructor. It's both a more and a less general solution, but C++'s
initialisation is vastly different to C's so that's to be expected.

> Wait... Wait just a moment... Is that why they did it? Was this a political
> movement? A battle? A rift among the ones with the pen and those actually
> down in the trenches? :-) Well my my.

I doubt it's anything so nefarious (what's to be gained?). C++
initialisation is very different to C initialisation, so maybe the
committee simply could fit, or could not do the work needed to fit,
designated initialisers into the C++ scheme of things.

<snip>
--
Ben.

Rick C. Hodgin

unread,
Aug 29, 2014, 3:49:44 PM8/29/14
to
On Friday, August 29, 2014 2:15:50 PM UTC-4, Ben Bacarisse wrote:
> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
> On C++ missing C's designated initialisers...
>
> > Does anyone know why the C++ designers prohibited this type of compile-time
> > initialization at any point? It rather significantly hobbles the general
> > use of unions, doesn't it? Limits their full functionality solely to
> > run-time code.
>
> No, because there is a C++ way to do this: supply an overloaded
> constructor. It's both a more and a less general solution, but C++'s
> initialisation is vastly different to C's so that's to be expected.


Do constructors work like that (for data populated into static blocks
at compile-time)? I always thought constructors were for data requested,
and therefore code executed, at run-time.

What would be the syntax for my example?

> --
> Ben.

Paavo Helde

unread,
Aug 29, 2014, 4:15:52 PM8/29/14
to
"Rick C. Hodgin" <rick.c...@gmail.com> wrote in
news:37e780ad-f774-41be...@googlegroups.com:
struct SExample
{
SExample(int i): x(0), i(i) {}
SExample(float f): x(1), f(f) {}
SExample(double d): x(2), d(d) {}
int x;
union {
int i;
float f;
double d;
};
};

SExample gList[] = {1, 1.0f, 2.0};

This is not compile-time though, but rather dynamic initialization of
static variables. So some code probably runs, but this happens before
main() is called.

HTH
Paavo

Victor Bazarov

unread,
Aug 29, 2014, 4:26:39 PM8/29/14
to
Also, isn't it true that SExample is thus no longer a POD? I mean,
formally, of course, but with all that it entails...

Ben Bacarisse

unread,
Aug 29, 2014, 4:40:25 PM8/29/14
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:

> On Friday, August 29, 2014 2:15:50 PM UTC-4, Ben Bacarisse wrote:
>> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
>> On C++ missing C's designated initialisers...
>>
>> > Does anyone know why the C++ designers prohibited this type of compile-time
>> > initialization at any point? It rather significantly hobbles the general
>> > use of unions, doesn't it? Limits their full functionality solely to
>> > run-time code.
>>
>> No, because there is a C++ way to do this: supply an overloaded
>> constructor. It's both a more and a less general solution, but C++'s
>> initialisation is vastly different to C's so that's to be expected.
>
> Do constructors work like that (for data populated into static blocks
> at compile-time)? I always thought constructors were for data requested,
> and therefore code executed, at run-time.
>
> What would be the syntax for my example?

You don't need any special syntax (I assume you know the syntax for a
constructor!) so if you've tried it, it's likely that you don't have a
new enough compiler. You need, I think, C++ 2011 ("extended initializer
lists").

<snip>
--
Ben.

Scott Neugroschl

unread,
Aug 29, 2014, 5:26:22 PM8/29/14
to
I think if you add trivial copy, move and default constructors, it
becomes a POD again. At least as of C++11. DISCLAIMER: IANALL,
nor do I play one on TV.

Jorgen Grahn

unread,
Aug 30, 2014, 12:53:07 AM8/30/14
to
On Fri, 2014-08-29, Rick C. Hodgin wrote:
> Is there a compile-time workaround for this in MSVC++?

> Currently I am using GCC through MinGW in Windows to compile the area
> of the program where I need this ability, and then linking them
> together. But, I'd rather figure out some way to do it in a single
> toolset.

> struct SExample
> {
> int x;
> union {
> int i;
> float f;
> double d;
> };
> };

...

> In GCC there's an extension, { 1, {.f = 1.0f} }, { 2, {.d = 2.0 } },
> which I believe comes forward from C and is supported in C++ through
> the GCC extensions (or possibly C11??).

It's from C99, and it wouldn't be available in g++ if you told it to
compile the code as C++ rather than the default, "C++ with whatever
extensions we happen to like right now".

Unnamed unions themselves seem to be C11, though.

I would solve the problem by using standard C++. This (fighting
multiple compilers) is one of the main reasons to have a standard.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Rick C. Hodgin

unread,
Aug 30, 2014, 9:10:07 AM8/30/14
to
On Saturday, August 30, 2014 12:53:07 AM UTC-4, Jorgen Grahn wrote:
> I would solve the problem by using standard C++. This (fighting
> multiple compilers) is one of the main reasons to have a standard.
> /Jorgen


FWIW, I view this as a fundamental flaw in the ISO C++ spec. It hobbles
the use of unions by limiting their full functionality to runtime code
only, and removes something that's not only possible, but rather trivial
at compile time.

It's one more feature added to my RDC list.

Jorgen Grahn

unread,
Aug 30, 2014, 10:06:08 AM8/30/14
to
On Sat, 2014-08-30, Rick C. Hodgin wrote:
> On Saturday, August 30, 2014 12:53:07 AM UTC-4, Jorgen Grahn wrote:
>> I would solve the problem by using standard C++. This (fighting
>> multiple compilers) is one of the main reasons to have a standard.
>> /Jorgen
>
>
> FWIW, I view this as a fundamental flaw in the ISO C++ spec. It hobbles
> the use of unions by limiting their full functionality to runtime code
> only, and removes something that's not only possible, but rather trivial
> at compile time.

If so, then it's also a fundamental flaw in C, from 1970 to 2011.
Hard to blame C++ for it.

> It's one more feature added to my RDC list.

What's an RDC list? Wikipedia is unhelpful.

Öö Tiib

unread,
Aug 30, 2014, 10:31:10 AM8/30/14
to
On Friday, 29 August 2014 16:24:54 UTC+3, Rick C. Hodgin wrote:
> Is there a compile-time workaround for this in MSVC++? Currently I am
> using GCC through MinGW in Windows to compile the area of the program
> where I need this ability, and then linking them together. But, I'd
> rather figure out some way to do it in a single toolset.
>
> struct SExample
> {
> int x;
> union {
> int i;
> float f;
> double d;
> };
> };
>
> SExample gList[] =
> {
> { 0, (int)1 },
> { 1, (float)1.0f }, // Warning (1)
> { 2, (double)2.0 } // Warning (2)
> };
>
> (1) warning C4244: 'initializing' : conversion from 'float' to 'int',
> possible loss of data
> (2) warning C4244: 'initializing' : conversion from 'double' to 'int',
> possible loss of data

That limit is in C++11 as well:
"8.5.1/15 When a union is initialized with a brace-enclosed initializer,
the braces shall only contain an initializer-clause for the first
non-static data member of the union."

> In GCC there's an extension, { 1, {.f = 1.0f} }, { 2, {.d = 2.0 } }, which
> I believe comes forward from C and is supported in C++ through the
> GCC extensions (or possibly C11??).
>
> Is there a compile-time workaround in MSVC++? Specifically, I'm using
> the MSVC++ tools that came with Visual Studio 2003 and Visual Studio 2008.

MS tool-set compiles only somewhat extended C89 AFAIK. So you can
not use that C feature with MS toolset. Even if you try to initialize your
variable in C (and only use it in C++) the MS C compiler will reject
the syntax.

> My MSVC++ workaround today is a run-time initialization. I initialize
> them to integer values (the first union member) in source code, and then
> in my custom init() code I manually populate those entries with their
> proper float and double values. The actual source code this example
> relates to is much longer and I have several that need updated. I'd
> rather figure out a way to do it entirely at compile time, and in the
> single MSVC++ toolset.

I personally avoid unions and use 'Boost.Variant' library instead
for its better type-safety, portability and usability. I do not exactly
know if it does initialize run-time or compile-time with MSVC 2008.
Variant constructors have never managed to participate noteworthy in
running profile of my programs.

Rick C. Hodgin

unread,
Aug 30, 2014, 10:37:28 AM8/30/14
to
On Saturday, August 30, 2014 10:06:08 AM UTC-4, Jorgen Grahn wrote:
> On Sat, 2014-08-30, Rick C. Hodgin wrote:
> > FWIW, I view this as a fundamental flaw in the ISO C++ spec. It hobbles
> > the use of unions by limiting their full functionality to runtime code
> > only, and removes something that's not only possible, but rather trivial
> > at compile time.
>
> If so, then it's also a fundamental flaw in C, from 1970 to 2011.
> Hard to blame C++ for it.

My blame is not solely limited to C++, but to any C-like language supporting
unions, yet not supporting initialization to any union member at compile-time.

> > It's one more feature added to my RDC list.
> What's an RDC list? Wikipedia is unhelpful.

RDC is the Rapid Development Compiler I am working on.
https://groups.google.com/forum/?fromgroups#!forum/rapid_development_compiler

I have a long-term goal. My work began on the current iteration of
my project in July, 2012 and continues today:
(1) Visual FreePro (which includes the Rapid Development Compiler)
(2) Exodus Operation System 32-bit
(3) Armodus Operation System 32-bit
(4) Exodus 64-bit version
(5) Armodus 64-bit version

Here are the outlines of the plan from way back:
http://www.visual-freepro.org/forum/viewtopic.php?f=3&t=14

Here is the overview of what I'm doing and why:
http://www.visual-freepro.org/wiki/index.php/Main_Page#Village_Freedom_Project

The current version of my built-from-the-ground-up IDE can be seen here:
http://www.visual-freepro.org/vjr/indexmain.html

Screenshot: http://www.visual-freepro.org/images/vjr_051.1.png

And here's the current source code I'm working on:
https://github.com/RickCHodgin/libsf/tree/master/source/vjr

Rick C. Hodgin

unread,
Aug 30, 2014, 10:40:59 AM8/30/14
to
I appreciate your input. Thank you.

Rick C. Hodgin

unread,
Aug 30, 2014, 2:47:48 PM8/30/14
to
My post was finally approved through moderation:
https://groups.google.com/forum/?fromgroups#!topic/comp.std.c++/1henU64d9is

We'll see what the true reasoning is. Perhaps I'm completely off the
reservation.

Rick C. Hodgin

unread,
Sep 14, 2014, 8:00:39 PM9/14/14
to
On Saturday, August 30, 2014 2:47:48 PM UTC-4, Rick C. Hodgin wrote:
> My post was finally approved through moderation:
> https://groups.google.com/forum/?fromgroups#!topic/comp.std.c++/1henU64d9is
>
> We'll see what the true reasoning is...

There has been no response in several days. In addition, I have posted
a follow-up asking that this limitation be removed, but it has not been
received through moderation, nor has an explanation been given as to
why it has not been received through moderation.

Any thoughts as to what's going on there?

Thank you in advance.

Mr Flibble

unread,
Sep 15, 2014, 12:58:30 PM9/15/14
to
The problem is that you are using VC++ 6.0 and nobody in this newsgroup
cares for or will answer questions related to that piece of shit compiler.

Again: VC++ 6.0 IS NOT A C++ COMPILER IT IS A VC++ 6.0 COMPILER.

/Flibble

Bo Persson

unread,
Sep 15, 2014, 2:11:58 PM9/15/14
to
There are a limited number of moderators. Sometimes it just happens that
all of them are busy doing other things for a couple of days.


To address you actual question of why the C++ standard says:

"When a union is initialized with a brace-enclosed initializer, the
braces shall only contain an initializer-clause
for the first non-static data member of the union." (§8.5.1/15)

This refers to the C standard that says (C99, §6.7.8/17):

"[...] subobjects of the current object are initialized in order
according to the type of the current object: array [...], structure
[...], and the first named member of a union."


So when C++ has braced initializers for C-like objects, the rules are
the same as in C. Seems rather logical.


Bo Persson

Rick C. Hodgin

unread,
Sep 15, 2014, 4:22:54 PM9/15/14
to
Thank you for this information. It is definitely working as it's defined.
I did not know the C++ reference tied back to something in C99.

So ... should I ask for the change to be added in something like
comp.std.c ??

I just don't see any reason why braced initializers should be limited
to the first member when their proper union member could be determined
by base type (float into the float union member, int into the int, and
so on so long or to be explicitly cast by name).

Victor Bazarov

unread,
Sep 15, 2014, 4:52:25 PM9/15/14
to
On 9/15/2014 4:22 PM, Rick C. Hodgin wrote:
>[..]
> I just don't see any reason why braced initializers should be limited
> to the first member when their proper union member could be determined
> by base type (float into the float union member, int into the int, and
> so on so long or to be explicitly cast by name).

It could be that providing for such a special case is simply not worth
the trouble...

Rick C. Hodgin

unread,
Sep 15, 2014, 5:10:32 PM9/15/14
to
> ...may not be worth the trouble.

Understood.

David Brown

unread,
Sep 16, 2014, 3:38:32 AM9/16/14
to
This is all related to a more general point - C++ does not support
designated initialisers that C introduced in C99. (gcc's extensions
here are just a refinement of that.) If you ever get an answer from the
standards folk, the usual reasoning is that C++ constructors provide a
better system than C's designated initialisers, and thus you should use
constructors.

Of course, this argument is nonsense - constructors are more flexible,
and better for some purposes, but take more effort to write, can't be
used for compile-time initialisation (perhaps they can now with
"constexpr"?), and are incompatible with C. Each method has its
advantages and disadvantages, and people want both.

The C++ standards folk really need to take a look at C11 and update
their C compatibility to take advantage of the improvements in C since
the schism. There is not much to do, but a few points would make a big
difference - designated initialisers is, IMHO, the most important. And
since gcc is quite happy with designated initialisers in C++, it seems
there would be no problem adding it to the language.


Initialising union members automatically by type is another matter. It
might work okay in simple cases, but it could quickly get complicated
and ambiguous, especially once classes with constructors got involved.
Designated initialisers are conceptually simpler, more explicit, and
more flexible.

Rick C. Hodgin

unread,
Sep 17, 2014, 7:00:52 PM9/17/14
to
On Tuesday, September 16, 2014 3:38:32 AM UTC-4, David Brown wrote:
> This is all related to a more general point - C++ does not support
> designated initialisers that C introduced in C99. (gcc's extensions
> here are just a refinement of that.) If you ever get an answer from the
> standards folk, the usual reasoning is that C++ constructors provide a
> better system than C's designated initialisers, and thus you should use
> constructors.

Compilers are tools. My thinking is this: I should not have to manually
do something the compiler can do for me. :-) When there is no ambiguity
in the initialization type, for example, the compiler should be able to
receive whatever I pass to it, and assemble it for me, at compile time
so I don't have to execute any code at runtime, nor perform the manual
steps of writing code which is executed at runtime.

struct SExample
{
union {
int i;
float f;
};
};

SExample myArray[] = {
{ 10 }, // Initialized into i
{ 29.7f } // Initialized into f
};

If there is any ambiguity about the type, then it could fall back to a
top-down method where it maps into the first one which is close, or
would use an algorithm, such as only directly mapping if the two or
twelve conflicting types available actually occupy the same memory space
within the union (because in such a case it really doesn't matter which
one it maps to because they all map to the same place in memory).

That also brings up another need as I see it... the ability to
explicitly indicate where a union should fall at compile time, and
without having to pad it manually.

struct SExample2
{
union {
double d;
char c;
};
};

I should be able to place these wherever I want them. In fact, for some
low-level purposes this would be desirable.

struct SExample2
{
union {
double d (|4,#,8|);
char c (|top|);
};
};

Something here like:
(|4,#,8|) indicates 4 bytes padding before, the # of bytes for the thing,
and then 8 bytes padding after. So in this case d would be initialized
to consume 20 bytes, with 4 bytes padding before the variable in memory,
then the 8 bytes d occupies, and then 8 bytes of padding after.

(|top|) would indicate that c should go to the top of the memory block
(to the greatest/highest memory address based on the other union members).

The storage for such a union would then be (in bytes):
d: [pad1 4:0,0,0,0][d 8:0,0,0,0,0,0,0,0][pad2 8:0,0,0,0,0,0,0,0]
c: [c 1:0][pad 19:0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

In addition, I should be able to manually indicate where I want something
to go to complete override its basic type, such as using an initializer
with a cask after, as in:

SExample myArray[] = {
{ 10 (|#,2,3|) }, // Initialized as 16-bits at offset 3
{ 29.7f } // Initialized into f
};

This would have the effect of increasing the sizeof(SExample) to 5
bytes because the position of the example here would run to offsets
3..4, which are bytes 4 and 5.

> Of course, this argument is nonsense - constructors are more flexible,
> and better for some purposes, but take more effort to write, can't be
> used for compile-time initialisation (perhaps they can now with
> "constexpr"?), and are incompatible with C. Each method has its
> advantages and disadvantages, and people want both.

I don't think anyone would suggest taking away constructors. :-)
They have their place for sure. But, right now, compile time
initialization to non-topmost union members is impossible without
reaching into a compiler extension like gcc's name designation.
That hindrance is unnecessary, and hampers the use of unions, a
perfectly valid tool in the developer's arsenal.

> The C++ standards folk really need to take a look at C11 and update
> their C compatibility to take advantage of the improvements in C since
> the schism. There is not much to do, but a few points would make a big
> difference - designated initialisers is, IMHO, the most important. And
> since gcc is quite happy with designated initialisers in C++, it seems
> there would be no problem adding it to the language.

Designated initializers should only be needed in special cases. But I
agree they should be available.

> Initialising union members automatically by type is another matter. It
> might work okay in simple cases, but it could quickly get complicated
> and ambiguous, especially once classes with constructors got involved.
> Designated initialisers are conceptually simpler, more explicit, and
> more flexible.

The compiler could set limits on things to keep them simple. If it is not
something that can be explicitly resolved at compile time using only basic
translation, then it is required to perform the operation at runtime.

However, even in such a case the compiler could still identify that it
is of such a kind and automatically generate the code so that it is
performed at runtime, even though it appears as though it was done
at compile time. The only issue there would be object code which contains
incomplete data as it has not yet initialized itself as one might
otherwise expect it should be given that the initialization was
performed by the developer at compile time.

I think that's a minor issue though. And I can't imagine a case where
initialization into a union member is so complex that it cannot be
resolved at compile time, or it can't have the code to automatically
populate into the appropriate location be automatically inserted and
performed at runtime.

Can you think of such an example?

Ben Bacarisse

unread,
Sep 17, 2014, 8:42:44 PM9/17/14
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:

> On Tuesday, September 16, 2014 3:38:32 AM UTC-4, David Brown wrote:
>> This is all related to a more general point - C++ does not support
>> designated initialisers that C introduced in C99. (gcc's extensions
>> here are just a refinement of that.) If you ever get an answer from the
>> standards folk, the usual reasoning is that C++ constructors provide a
>> better system than C's designated initialisers, and thus you should use
>> constructors.
>
> Compilers are tools. My thinking is this: I should not have to manually
> do something the compiler can do for me. :-) When there is no ambiguity
> in the initialization type, for example, the compiler should be able to
> receive whatever I pass to it, and assemble it for me, at compile time
> so I don't have to execute any code at runtime, nor perform the manual
> steps of writing code which is executed at runtime.
>
> struct SExample
> {
> union {
> int i;
> float f;
> };
> };
>
> SExample myArray[] = {
> { 10 }, // Initialized into i
> { 29.7f } // Initialized into f
> };

Did you not just argue against one use of auto because you did not want
the meaning to depend on a detail like the type of a constant? In that
case, there is a chance the compiler will pick up such a mistake later,
but that's not possible with this proposal.

<snip>
--
Ben.

Rick C. Hodgin

unread,
Sep 17, 2014, 9:54:11 PM9/17/14
to
On Wednesday, September 17, 2014 8:42:44 PM UTC-4, Ben Bacarisse wrote:
> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
> > struct SExample
> > {
> > union {
> > int i;
> > float f;
> > };
> > };
> >
> > SExample myArray[] = {
> > { 10 }, // Initialized into i
> > { 29.7f } // Initialized into f
> > };
>
> Did you not just argue against one use of auto because you did not want
> the meaning to depend on a detail like the type of a constant?

The constant in the auto reference had no definition to tie back to, and
was entirely dependent upon its use in the function body for its type,
allowing the error to potentially exist and be uncaught because it has
no correlation due to auto. In this case the definition is provided in
the union members. And while the possibility still exists of making a
mistake and providing the incorrect form in the initializer, it would
be less likely in my estimate because it would require the developer
make two mistakes rather than just one (1-forgetting the proper
declaration in the union, and 2-using an initializer form which could
be readily translated into an existing type).

It is still possible though. When you use unions there are some
tradeoffs, and this is one of them (no direct typing, so the
possibility of errors increases).

> In that case, there is a chance the compiler will pick up such a
> mistake later, but that's not possible with this proposal.
> Ben.

My personal preference would be that all initializers line up exactly,
and if not then generate a compiler error so they must be explicitly
cast to convey original intent.

And in the case of there being some ambiguity, such as 5 being used as
an initializer on a union which has both int and char members, and
because the value 5 is within range of both and ambiguity exists, then
they too should be explicitly cast -- unless they both translate into
a compiled byte form which maps to the same memory location within
the union, in which case it is automatically resolved by the
peculiarities of the instance declaration, and the cast becomes
unnecessary.

Ben Bacarisse

unread,
Sep 18, 2014, 8:33:52 AM9/18/14
to
"Rick C. Hodgin" <rick.c...@gmail.com> writes:

> On Wednesday, September 17, 2014 8:42:44 PM UTC-4, Ben Bacarisse wrote:
>> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
>> > struct SExample
>> > {
>> > union {
>> > int i;
>> > float f;
>> > };
>> > };
>> >
>> > SExample myArray[] = {
>> > { 10 }, // Initialized into i
>> > { 29.7f } // Initialized into f
>> > };
>>
>> Did you not just argue against one use of auto because you did not want
>> the meaning to depend on a detail like the type of a constant?
>
> The constant in the auto reference had no definition to tie back to, and
> was entirely dependent upon its use in the function body for its type,
> allowing the error to potentially exist and be uncaught because it has
> no correlation due to auto.

Though, since the type of the function is affected, it might get caught
later on in the compile. An error in the above can never be caught
because the types are all correct.

> In this case the definition is provided in
> the union members. And while the possibility still exists of making a
> mistake and providing the incorrect form in the initializer, it would
> be less likely in my estimate because it would require the developer
> make two mistakes rather than just one (1-forgetting the proper
> declaration in the union, and 2-using an initializer form which could
> be readily translated into an existing type).

Maybe you did not get what I was referring to. An error (which can't be
caught later on) can be introduced but a single character typo. Only
one mistake is needed.

<snip>
> And in the case of there being some ambiguity, such as 5 being used as
> an initializer on a union which has both int and char members, and
> because the value 5 is within range of both and ambiguity exists,

5 is "in range" for a very large number of types (especially if the
member has constructors defined). But this is C++ not C, and in C++ the
programmer can differentiate between an int (5) and a char ('\5').

<snip>
--
Ben.

Rick C. Hodgin

unread,
Sep 18, 2014, 9:48:23 AM9/18/14
to
On Thursday, September 18, 2014 8:33:52 AM UTC-4, Ben Bacarisse wrote:
> "Rick C. Hodgin" <rick.c...@gmail.com> writes:
> > On Wednesday, September 17, 2014 8:42:44 PM UTC-4, Ben Bacarisse wrote:
> >> Did you not just argue against one use of auto because you did not want
> >> the meaning to depend on a detail like the type of a constant?
> >
> > The constant in the auto reference had no definition to tie back to, and
> > was entirely dependent upon its use in the function body for its type,
> > allowing the error to potentially exist and be uncaught because it has
> > no correlation due to auto.
>
> Though, since the type of the function is affected, it might get caught
> later on in the compile. An error in the above can never be caught
> because the types are all correct.

It's possible.
0 new messages