The initialization of constant structure members in C / C ++ ... depends on the compiler?

I recently encountered a compiler error in an outdated environment using Borland C ++ 5.2. I had a .cpp file that included a header from some C source that I do not control. The header contained a structure definition that included const members, and the compiler complained of a "constant member in a class without constructors". When investigating this error, it seems to depend on the compiler. Here is some sample w / code of the results from different compilers:

#include <stdio.h> typedef struct { const float a; } _floater; int main() { _floater f = {5.1F}; printf("%f\r\n",fa); return 0; } 

Borland 5.2

 E:\Projects\Scratchpad>bcc32 -P const_float.c Borland C++ 5.2 for Win32 Copyright (c) 1993, 1997 Borland International const_float.c: Error const_float.c 13: Constant member ' ::a' in class without constructors *** 1 errors in Compile *** 

Microsoft VS 2003.NET:

 E:\Projects\Scratchpad>cl /TP const_float.c Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86 Copyright (C) Microsoft Corp 1984-1998. All rights reserved. const_float.c const_float.c(19) : error C2552: 'f' : non-aggregates cannot be initialized with initializer list 

Microsoft VS 2008:

 C:\Projects\Scratchpad>cl /TP const_float.c Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. const_float.c Microsoft (R) Incremental Linker Version 9.00.21022.08 Copyright (C) Microsoft Corporation. All rights reserved. /out:const_float.exe const_float.obj C:\Projects\Scratchpad>const_float.exe 5.100000 

g ++ 3.3.3

 $ g++ const_float.c -o const_float.exe const_float.c:25:2: warning: no newline at end of file $ ./const_float.exe 5.100000 

Note that Borland fails when declaring a struct because it has a const member but no constructors, while VS 2003 is fine with the declaration, but complains when you try to create it using a list of initializers - given the non-aggregate structure a type. VS2008 and g ++ are completely happy. [Apologies .. I just realized that the #s line in the errors is incorrect, because I deleted some commented lines before posting.]

The definition of Microsofts aggregates is here: http://msdn.microsoft.com/en-us/library/0s6730bb.aspx . It did not seem to me that const members would make the structure non-aggregate, but perhaps they returned in 2003.

It also seems that the latest Borland compiler (Embarcadero) sees this as a warning, not an error: http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devwin32/wrnmembnocons_xml.html .

So, 2 questions that I assume:

  • Why dispersion in compilers? Is the standard ambiguous at this point?
  • Any workarounds? Given that I am stuck with the compiler version and the header file, I do not see.

Thanks!

+5
source share
4 answers

The standard is pretty clear. Having a const member does not limit the class to an aggregate.

8.5.1 [dcl.init.aggr]

An aggregate is an array or class (section 9) without constructors declared by the user (12.1), without private or protected non-static data elements (section 11), without base classes (section 10) and without virtual functions (10.3).

It is legal to copy-initialize a const object, and this is the initialization that aggregate initialization performs on the members of the aggregate. The restrictions on naming a const object without a constructor declared by the user in the mem-initializer list in 12.6.2 apply only to initialization with a constructor, which is not applied, because aggregation is initialized instead.

As for the old compilers, I do not know. I can only say that they do not meet the standard in this regard.

+7
source

Question 1:

Compilers published at different times use different versions of C ++. They represent various approximations to the standard. Everyone has "add-ons" for a particular provider, i.e. Allow portable code.

  • BCC 5.2 was created before the first C ++ standard (ISO 14882: 1998).
  • VC ++ 2003 is close to ISO 14882: 1998, but also has some drawbacks, especially regarding templates.
  • VC ++ 2008 almost implements ISO 14882: 2003.

Question 2:

  • Try creating a modern compiler for an outdated system if it is 32-bit Windows.
  • Try compiling on a modern machine and deploy the executable to your old system.
  • If the legacy system is 16-bit Windows, I don't see a solution.
+2
source

In g ++ 4.6.1 on the same Linux machine, -Wall -ansi -pedantic does not display any warnings.

This question may not have been so high on the agenda of compiler authors. It looks like this for me, looking at the behavior of VS2003 and VS2008 and looking at the behavior of g ++ 3.3.3 that you posted and the behavior of g ++ 4.6.1 that I observed.

Is it possible to change const to a private: not const? Thus, you will still have control over who writes to it, not exporting the installer for it, and not generating compiler errors.

+1
source

Just add more information on this subject for MSVC and g ++ and repeat what @Charles Bailey and @ René Richter said; Its acceptable are C ++ 03 and C ++ 11, but depending on the age and implementation status of your compiler, you will get different errors, if at all.

In fact, I tried the Dinkum online testing compilers for EDG, MSVC2008 and g ++, and everyone compiled the sample you gave, but NOT the sample I give below.

So, in short, fully initialized structures with constant members will successfully compile on MSVC2008 and g ++ 4.5, however, from proven compilers, no one can compile “partially initialized” (or partially aggregate initialized) POD structures, even if this is also acceptable in the C ++ standard. I even contacted some supporting g ++ errors to make sure I read this standard correctly and they confirmed that it should work even in current C ++ 03 compilers.

You can see related errors for this on both GNU Bugzilla and the Microsoft Visual Studio Help pages that were actually related to this fooobar.com/questions/895617 / ... , which is also related to Microsoft Error C3852 as a known behavior even MSVC2010

 // All sections refer to Draft C++03 (brackets refer to draft C++11) // // 3.9.3 CV (const/volatile) definition as "const data-type [= optional init]" // 7.1.5.1/1 The cv-qualifiers [ 7.1.6.1/1 in C++11 ] // "init-declarator-list of the declaration shall not be empty" const int constval = 10 ; // HOWEVER: // 7.1.5.1/2 The cv-qualifiers [ 7.1.6.1 in C++11 ] // [Note: as described in 8.5, the definition of an object or subobject // of const-qualified type must specify an initializer or be subject to // default-initialization. ] // 8.5 Initializers // 8.5/9 (C++11 8.5/11) // Otherwise, if no initializer is specified for a non-static // object, the object and its sub-objects, if any, have an indeterminate // initial value(*90); if the object or any of its sub-objects are of // const-qualified type, the program is ill-formed. // // *90: This does not apply to aggregate objects with automatic storage // duration initialized with an incomplete brace-enclosed initializer list // see 8.5.1. // [ C++11 this sub-clause has been removed, however the list-initializer section // pretty much covers the same topic - see 8.5.1/7 below ] // // 8.5.1 Aggregate definition // 8.5.1/7 (C++11 8.5.1/7) // If there are fewer initializers in the list than there are members in the // aggregate, then each member not explicitly initialized shall be // value-initialized (8.5). // // 8.5/5 value initialization // if T is a class type (clause 9) with a user-declared constructor // (12.1), then the default constructor for T is called (and the // initialization is ill-formed if T has no accessible default constructor) // ... // otherwise, the object is zero-initialized // // 8.5/5 zero initialization // if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T; // // POD type struct A { int n ; const int m ; // "const" causes failure in MSVC to make default constructor } ; // Example of non-POD struct B { int bbb ; B(){} } ; #include <stdio.h> int main() { // C++03/11 ill formed code, fails as expected const int c0 ; // per 7.1.5.1 "not allowed to be default init" // OK const int c = *new int ; // A default initialized constant const int c2 = *new int(); // A zero-init, above is DEFAULT-INIT printf( "c: %i\n", c ) ; // should be an undef-value printf( "c2: %i\n", c2 ) ; // should be 0 // OK ; Array example making sure it works const int aa[5] = {}; // all items value->zero-initialized per the above 8.5.1/7 printf( "aa: %i %i %i\n", aa[0], aa[2], aa[4] ) ; // C++03/11 ill formed code, no initializer (G++/MSVC should fail) A a0 ; // Correct error - no default constructor or initializer (8.5/9) // C++03/11 correctly formed code, full initializer list (G++/MSVC should pass) A a1 = {1,2}; // Explicit initialization OK, G++/MSVC pass // C++03/11 correctly formed code; copy initialized from a value-initialized A() A a2 = A(); // G++ OK, MSVC FAIL // C++03/11 correctly formed code; aggregate partial intializer (8.5.1/7 agg list init) A a3 = {}; // G++/MSVC FAIL A a4{}; // C++11 only - doesnt work in G++ (didnt try MSVC2010) printf( "a0.m=%i\n", a0.m ) ; // a0 should not exist due compile errors printf( "a1.m=%i\n", a1.m ) ; // a1.m should be 2 printf( "a2.m=%i\n", a2.m ) ; // a2.m should be 0 printf( "a3.m=%i\n", a3.m ) ; // a3.m should be 0 // C++03/11 correctly formed code; user-default constructor supplied. const B bee1 ; // Default constructor marks bbb as "initialized" const B bee2 = {} ; // CORRECTLY flagged error; init of non-aggregate printf( "%i\n", bee1.bbb ) ; } 
0
source

Source: https://habr.com/ru/post/895619/


All Articles