0

Having referenced this question: Can an enum class be converted to the underlying type?.

In my code I have effectively:

enum class STATE : short
{
    EMPTY,
    PRESENT,
    PARTIAL,
};

volatile STATE state;

Then I write a typedef and a static_assert:

typedef volatile std::underlying_type<STATE> state_type;
static_assert (sizeof (state_type) == sizeof (short), "Error - unsafe for use with InterlockedCompareExchange16");

Finally I attempt to set the state with InterlockedCompareExchange16:

if (InterlockedCompareExchange16 (static_cast<state_type *>(&state), STATE::PRESENT, STATE::EMPTY) == STATE::EMPTY)
{
}

I am getting the following errors from VS2012:

  1. My static_assert fails complaining that state_type is not the same size as short

  2. The static_cast complains that it cannot cast from volatile STATE * to state_type *

Please can anyone give me any pointers for how to best fix my code?

Community
  • 1
  • 1
Coder_Dan
  • 1,815
  • 3
  • 23
  • 31
  • Please do not modify the question in response to answers. It is confusing for people coming to the question later and makes the answers redundant. Rolled back. – hmjd May 16 '13 at 13:58
  • Just to admit my failing, previous errors mentioned were down to me incorrectly using 'underlying_type', but I still get the 'static_cast' complaining. – Coder_Dan May 16 '13 at 13:58
  • Sorry @hmjd. I've just added an explanatory comment - is that sufficient? – Coder_Dan May 16 '13 at 13:59

1 Answers1

2

From std::underlying_type:

Defines a member typedef type of type that is the underlying type for the enumeration T.

Change to:

typedef typename std::underlying_type<STATE>::type state_type;
                                            //^^^^

A motivation for the strongly typed enum class was to prevent conversion to int, so attempting to cast to the underlying type conflicts with the intended use of the enums (see Strongly Typed Enums (revision 3)).

Instead of using OS specific threading mechanisms use std::atomic<> template that was added to c++11:

std::atomic<STATE> state(STATE::EMPTY);
STATE expected(STATE::EMPTY);
if (state.compare_exchange_strong(expected, STATE::PRESENT))
{
    // 'state' set to 'PRESENT'.
}

This removes the requirement for static_assert and does not require any casting.

hmjd
  • 120,187
  • 20
  • 207
  • 252
  • Thank you - yes, I just spotted that error myself. This fixes one error - I still get the 'static_cast' complaining. I will update the question. – Coder_Dan May 16 '13 at 13:54
  • Unfortunately the Microsoft compiler gives the error: C2664: '_InterlockedCompareExchange16' : cannot convert parameter 1 from 'volatile STATE *' to 'volatile SHORT *' if I don't perform any cast. – Coder_Dan May 16 '13 at 14:02
  • I think that my core problem was that incorrect usage of std::underlying_type though. Should I close the question since it's unlikely to benefit other people. – Coder_Dan May 16 '13 at 14:05