4

I just can't find out how this simple example can be compiled in C++ :

class C
{
  public:
    static const void* noop = static_cast<const void*> (0x1);
};

Because of the static storage constraint I want, the only cast possible here would be static_cast but it is incompatible with this int-to-ptr cast.

error: invalid static_cast from type ‘int’ to type ‘const void*’

How can an integer value be statically casted to a pointer type?

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
Julio Guerra
  • 5,523
  • 9
  • 51
  • 75

4 Answers4

4

The problem here is that although you are declaring a const void* the const qualifier doesn't apply to the pointer but to the address that this pointer points to.

This means that noop is not a static const member variable and as all non const static member variables needs to be defined and initialized in a single translation unit outside class's definition like the example below:

class C {
  public:
    static const void *noop;
};

const void* C::noop = (const void*) 0x1;

Live Demo

The following solution:

class C {
public:
  static constexpr const void* noop = reinterpret_cast<const void*>(0x1);
};

Although, it compiles and works fine in GCC isn't valid C++ (e.g., it doesn't compile with either clang or VC++2013) because according to the standard § 5.19/2 Constant Expressions [expr.const] the result of a reinterpret_cast can't be a constant expression.

101010
  • 41,839
  • 11
  • 94
  • 168
3

reinterpret_cast is what you are looking for (raw interpretation of the bytes of an int to a const void* pointer)

Also, you need constexpr for in-class initialization of static data member :

class C
{
  public:
    static constexpr const void* noop = reinterpret_cast<const void*>(0x1);
};

static_cast doesn't work since there is no combination of user-defined or implicit conversions that would transform an int to a const void*.

EDIT:

This solution is not standard C++ (reinterpret_cast is not allowed in constant expressions), 40two solution's is correct.

Community
  • 1
  • 1
quantdev
  • 23,517
  • 5
  • 55
  • 88
1

40two has fixed the compile error, but also made the member non-const, which is undesirable because it hinders optimization and opens to door to accidental mutation.

Best:

class C {
  public:
    static const void* const noop;
};

const void* const C::noop = reinterpret_cast<const void*>(0x1);
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
0

An alternate solution which also comes from the question 40two references: constexpr and initialization of a static const void pointer with reinterpret cast, which compiler is right?, is to use intptr_t which is:

integer type capable of holding a pointer

This also allows you to make the member variable a constexpr:

class C
{
  public:
    static constexpr intptr_t noop = 0x1 ;
};

then you can use reinterpret_cast at the point where it is used:

const void * vPtr = reinterpret_cast<void*>( C::noop ) ;
Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740