How to constexpr construct C++ object containing reinterpret_cast pointer?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I need to define a C++ class with the following properties:

1) Global/static instances are constexpr constructed in the .data segment,
fully initialized, without runtime execution of a constructor.
2) A private or protected reference or const pointer member (not a pointer
to const or const reference) to a different object at an arbitrary memory
location.

The following example fails because reinterpret_cast is not allowed in a
constexpr:

```
struct S { unsigned u; };

class C {
  public:
    constexpr C(
    S* const s)
    :   _s(s)
    {}
    void set() const { _s->u = 0x87654321; }
  protected:
    S* const     _s;
};

constexpr S* const s = reinterpret_cast<S*>(0x40000000);  // compile error
C   c(s);

int main()
{
    c.set();
}
```

Removing constexpr by changing the above to:

S* const s = reinterpret_cast<S*>(0x40000000);

will compile, but violates requirement #1 -- the object is compiled into the
.bss segment and a constructor is generated which must be called by
pre-main() startup code.

Using brace-initialization (either C-style with "=", or C++ uniform
iniitialization without) does compile the object, initialized, in .data but
all members must be public -- if any members are private/protected the
brace-initialization will fail to compile.

```
struct S { unsigned u; };

struct C {
    void set() const { s->u = 0x87654321; }
    S* const     s;
};

C c = { reinterpret_cast<S*>(0x40000000) };

int main()
{
    c.set();
}
```

The closest thing to a solution I've found is:

```
struct S { unsigned u; };

class C {
  public:
    constexpr C(
    unsigned    u)
    :   _u(u)
    {}
    void set() const { _s()->u = 0x87654321; }
  protected:
    volatile S* _s() const { return reinterpret_cast<S*>(_u);}
    const unsigned  _u;
};

C c(0x40000000);

int main()
{
    c.set();
}
```

But this requires the extra "_s()" method which adds complexity and obscures
the code's intent.

Note that in GCC 4.8.3, prior to the changes for standards compliance as per
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49171, the constexpr cast did
not cause compilation error and the first example above worked as desired.
I've looked at the upcoming C++20 bit_cast operator, but
https://docs.w3cub.com/cpp/numeric/bit_cast/ specifically states it will not
allow pointers.

I welcome suggestions for workarounds with current or planned GCC versions
that satisfy both the requirements stated above. I had advocated for a GCC
extension in the Bugzilla URL, but was advised to post here instead. Pending
answers, I may file a separate Bugzilla request or discuss this further on
the general GCC mailing list or in the C++ community at large.

Note that the use-case for this is in embedded microcontroller programming,
where hardware resources appear as memory-accessed structs at arbitrary
locations in the address space. I frequently advocate for C++ as an equal or
superior language to C for this kind of low-level coding (likewise for
operating system kernels and drivers). Many disagree, and pending some new
solution I haven't found, in this specific case I'll have to reluctantly
agree.




--
Sent from: http://gcc.1065356.n8.nabble.com/gcc-Help-f629689.html



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux