简体   繁体   中英

Differences in narrowing in C++11 between assignment and initialiser lists

C++11 has given us initialiser lists. I've learned that these do not perform narrowing conversions, which sometimes breaks compilation of existing code, for example when operating on enum values with implicitly int-widened values:

   enum COMMAND
   {
     COMMAND_WRITE_MISC_CONFIG = 0x70
   };


   struct CommandSettings
   {
     quint8 buddy;
   };


   void NarrowingTest::testNarrowing()
   {
     quint8 i = 100;
     CommandSettings test{static_cast<quint8>(COMMAND_WRITE_MISC_CONFIG | i)};
     quint8 x = COMMAND_WRITE_MISC_CONFIG | i;
     QVERIFY(true);
   }      

The initialisation of test wouldn't compile without the cast.

What I'm looking for is the rationale behind the assignment initialisation of x still working.

CommandSettings test{static_cast<quint8>(COMMAND_WRITE_MISC_CONFIG | i)};

It is an aggregate initialization .

From the reference above:

The effects of aggregate initialization are:

...

If the initializer clause is an expression, implicit conversions are allowed as per copy-initialization, except if they are narrowing (as in list-initialization) (since C++11) .


quint8 x = COMMAND_WRITE_MISC_CONFIG | i;

It is a copy initialization .

From the reference above:

The effects of copy initialization are:

...

Otherwise (if neither T nor the type of other are class types), standard conversions are used , if necessary, to convert the value of other to the cv-unqualified version of T.

It should allow narrowing conversions at least for backward compatibility.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM