Почему одно и то же правило компиляции «reinterpret_cast не является постоянным выражением» не применяет аналогичные типы? - PullRequest
0 голосов
/ 08 мая 2020

У меня есть 3 подобных объединения c ++, как показано ниже, только U16_u не может быть скомпилировано, а U32_u и U64_u работают хорошо.

Сообщение об ошибке: «reinterpret_cast не является постоянным выражением».

constexpr U16_u( const char* p ) : asU( *reinterpret_cast<const uint16_t*>( p ) ) {};

                                                                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Почему то же правило не применяет эти очень похожие типы?

union U16_u {
   U16_u() noexcept = default;
   constexpr U16_u( const U16_u& ) noexcept = default;
   constexpr U16_u( U16_u&& ) noexcept = default;
   constexpr U16_u& operator=( const U16_u& ) noexcept = default;
   constexpr U16_u& operator=( U16_u&& ) noexcept = default;

   constexpr U16_u( uint16_t u ) : asU( u ) {};
   constexpr U16_u( int16_t i )  : asI( i ) {};
   constexpr U16_u( const char* p )
      : asU( *reinterpret_cast<const uint16_t*>( p ) ) {};  //ERROR

   constexpr U16_u& operator=( uint16_t u ) noexcept {
      asU = u;
      return *this;
   };
   constexpr U16_u& operator=( int16_t i ) noexcept {
      asI = i;
      return *this;
   };
   constexpr U16_u& operator=( const char* p ) noexcept {
      asU = *reinterpret_cast<const uint16_t*>( p );
      return *this;
   };

   constexpr bool operator< ( U16_u other ) const noexcept {
      return asU <  other.asU;
   };
   constexpr bool operator> ( U16_u other ) const noexcept {
      return asU >  other.asU;
   };
   constexpr bool operator!=( U16_u other ) const noexcept {
      return asU != other.asU;
   };
   constexpr bool operator==( U16_u other ) const noexcept {
      return asU == other.asU;
   };

   constexpr std::string_view strVw() const noexcept {
      return std::string_view( asA, sizeof( uint16_t ) );
   };

   std::string to_str() const noexcept {
      return std::string( asA, sizeof( uint16_t ) );
   };

   uint16_t asU;
   int16_t  asI;
   char     asA[ sizeof( uint16_t ) ];
   struct   {
      uint8_t b0;
      uint8_t b1;
   };
};

union U32_u {
   U32_u() noexcept = default;
   constexpr U32_u( const U32_u& ) noexcept = default;
   constexpr U32_u( U32_u&& ) noexcept = default;
   constexpr U32_u& operator=( const U32_u& ) noexcept = default;
   constexpr U32_u& operator=( U32_u&& ) noexcept = default;

   constexpr U32_u( uint32_t u ) : asU( u ) {};
   constexpr U32_u( int32_t i )  : asI( i ) {};
   constexpr U32_u( float f )    : asF( f ) {};
   constexpr U32_u( const char* p ) : asU( *reinterpret_cast<const uint32_t*>( p ) ) {};

   constexpr U32_u& operator=( uint32_t u ) noexcept {
      asU = u;
      return *this;
   };
   constexpr U32_u& operator=( int32_t i ) noexcept {
      asI = i;
      return *this;
   };
   constexpr U32_u& operator=( float f ) noexcept {
      asF = f;
      return *this;
   };
   constexpr U32_u& operator=( const char* p ) noexcept {
      asU = *reinterpret_cast<const uint32_t*>( p );
      return *this;
   };

   constexpr bool operator< ( U32_u other ) const noexcept {
      return asU <  other.asU;
   };
   constexpr bool operator> ( U32_u other ) const noexcept {
      return asU >  other.asU;
   };
   constexpr bool operator!=( U32_u other ) const noexcept {
      return asU != other.asU;
   };
   constexpr bool operator==( U32_u other ) const noexcept {
      return asU == other.asU;
   };

   constexpr std::string_view strVw() const noexcept {
      return std::string_view( asA, sizeof( uint32_t ) );
   };

   std::string to_str() const noexcept {
      return std::string( asA, sizeof( uint32_t ) );
   };

   uint32_t asU;
   int32_t  asI;
   float    asF;
   char     asA[ sizeof( uint32_t ) ];
   struct   {
      uint16_t w0;
      uint16_t w1;
   };
   struct   {
      uint8_t b0;
      uint8_t b1;
      uint8_t b2;
      uint8_t b3;
   };
};

union U64_u {
   U64_u() noexcept = default;
   constexpr U64_u( const U64_u& ) noexcept = default;
   constexpr U64_u( U64_u&& ) noexcept = default;
   constexpr U64_u& operator=( const U64_u& ) noexcept = default;
   constexpr U64_u& operator=( U64_u&& ) noexcept = default;

   constexpr U64_u( uint64_t u ) : asU( u ) {};
   constexpr U64_u( int64_t i )  : asI( i ) {};
   constexpr U64_u( double d )   : asD( d ) {};
   constexpr U64_u( const char* p ) : asU( *reinterpret_cast<const uint64_t*>( p ) ) {};

   //void operator=( const U64_u& o ) volatile noexcept { asU = o.asU; };

   constexpr U64_u& operator=( uint64_t u ) noexcept {
      asU = u;
      return *this;
   };
   constexpr U64_u& operator=( int64_t i ) noexcept {
      asI = i;
      return *this;
   };
   constexpr U64_u& operator=( double d ) noexcept {
      asD = d;
      return *this;
   };
   constexpr U64_u& operator=( const char* p ) noexcept {
      asU = *reinterpret_cast<const uint64_t*>( p );
      return *this;
   };

   constexpr bool operator< ( U64_u other ) const noexcept {
      return asU <  other.asU;
   };
   constexpr bool operator> ( U64_u other ) const noexcept {
      return asU >  other.asU;
   };
   constexpr bool operator!=( U64_u other ) const noexcept {
      return asU != other.asU;
   };
   constexpr bool operator==( U64_u other ) const noexcept {
      return asU == other.asU;
   };

   constexpr std::string_view strVw() const noexcept {
      return std::string_view( asA, sizeof( uint64_t ) );
   };

   std::string to_str() const noexcept {
      return std::string( asA, sizeof( uint64_t ) );
   };

   uint64_t asU;
   int64_t  asI;
   double   asD;
   char     asA[ sizeof( uint64_t ) ];
   struct   {
      uint16_t w0;
      uint16_t w1;
      uint16_t w2;
      uint16_t w3;
   };
   struct   {
      uint8_t b0;
      uint8_t b1;
      uint8_t b2;
      uint8_t b3;
      uint8_t b4;
      uint8_t b5;
      uint8_t b6;
      uint8_t b7;
   };
};

Я знаю, что эту проблему можно решить посредством "constexpr U16_u (const char * p): b0 (p [0]), b1 (p [1]) {};" или другие простые методы, но меня интересует вопрос.

...