Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to cast nonconst variable to constant static integral class member variable via reinterpret_cast in C++?

I am reading a book on writing modern C++ code for microcontrollers which is named "Real time C++". I am trying to write the codes in the book myself. However, while copying the code from the book and trying to build it, I got a compilation error of:

error C2131: expression did not evaluate to a constant.
message : a non-constant (sub-) expression was encountered

I inserted the relevant part of the code below:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#include <cstdint>
#include <iomanip>
#include <iostream>
namespace mcal
{
  namespace reg
  {
    // Simulate the transmit and receive hardware buffers on the PC.
    std::uint8_t dummy_register_tbuf;
    std::uint8_t dummy_register_rbuf;
  }
}

class communication
{
  private:
    static constexpr std::uint8_t* tbuf = reinterpret_cast<std::uint8_t*>(&mcal::reg::dummy_register_tbuf); 
    static constexpr std::uint8_t* rbuf = reinterpret_cast<std::uint8_t*>(&mcal::reg::dummy_register_rbuf);
};

/* rest of the nonrelated code */

The error indicates those two lines where casting happens. I know that we try to use static constexpr integral class member variables, because this ensures optimization (constant folding) on them. I think that the error happens because we try to set a nonconstant variable to a constant variable, but I can be wrong surely. So, I would kindly ask you to explain to me what is the real problem here and why the author did such a mistake (if it is a mistake). Also, if you additionally point out the correct way of casting I would highly appreciate. Thank you very much.

>Solution :

It is unclear what the intention behind the reinterpret_cast is, but the program is ill-formed.

constexpr on a variable requires that the initializer is a constant expression. But an expression is disqualified from being a constant expression if it would evaluate a reinterpret_cast. Therefore the initialization is ill-formed.

However, nothing else in the initialization stops it from being a constant expression and so

static constexpr std::uint8_t* tbuf = &mcal::reg::dummy_register_tbuf; 

will just work and the reinterpret_cast would be a redundant anyway since it would cast between identical pointer types which is specified to result in the same value.

GCC, ICC and MSVC up to v19.16 do seem to erroneously accept the code (https://godbolt.org/z/YKjhxqo3v). Maybe the author tested the code only on one of these compilers.

For GCC there is a bug report here.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading