Get address of object cast to arithmetic type at compile time

I’m trying to implement x86 page tables/page directories in C++ and I would like to be able to construct these at compile time. In order to do this I need to be able to obtain the address of static constexpr page table objects at compile time, cast to an arithmetic type, such that I can use them to construct static constexpr page directory entries as such:

struct PageTable {
  /* ... */
};

struct PageDirectory {
  constexpr PageDirectory(std::initializer_list<uint32_t> entries)
  { /* ... */ }

  /* ... */
};

static constexpr PageTable pt { /* ... */ };

static constexpr PageDirectory pd {
  reinterpret_cast<uint32_t>(&pt) | WRITE | PRESENT,

  /* ... */
};

This does not work because reinterpret_cast cannot be used inside a constant expression. Is there any other way I could realize this or something similar?

>Solution :

At compile-time, you’re not generally allowed to do low-level chicanery like accessing the numerical value of an address. Even C++20’s bit_cast is explicitly not constexpr if the source object is (or contains) a pointer.

This is important because the address of things at runtime is not the same as their compile-time address. Indeed, the part of your build system that deals with constant evaluation (aka: the compiler) is not the same part of the build system that deals with assigning addresses to things (aka: the linker). Since the compiler cannot see the future, it is incapable of computing what the runtime address of a compile-time object will be.

Of course, there’s also the fact that the linker itself may not know what that address will be, as modern OS’s typically assign executables to arbitrary virtual addresses that are different with each loading of the executable. And while the linker/OS doesn’t have to do this, the language does need to take this into account in terms of its design. That is, it can’t do something that would make such things impossible or infeasible to implement.

Leave a Reply