简体   繁体   中英

Modifying scoped enum by reference

I am increasingly finding scoped enums unwieldy to use. I am trying to write a set of function overloads including a template for scoped enums that sets/initializes a value by reference--something like this:

void set_value(int& val);
void set_value(double& val);
template <typename ENUM> set_value(ENUM& val);

However, I don't quite see how to write the templated version of set_value without introducing multiple temporary values:

template <typename ENUM>
set_value(ENUM& val)
{
  std::underlying_type_t<ENUM> raw_val;
  set_value(raw_val);    // Calls the appropriate "primitive" overload
  val = static_cast<ENUM>(raw_val);
}

I believe the static_cast introduces a second temporary value in addition to raw_val . I suppose it's possible that one or both of these could be optimized away by the compiler, and in any case it shouldn't really make much difference in terms of performance since the set_value call will also generate temporary values (assuming it's not inlined), but this still seems inelegant. What I would like to do would be something like this:

template <typename ENUM>
set_value(ENUM& val)
{
  set_value(static_cast<std::underlying_type_t<ENUM>&>(val));
}

... but this isn't valid (nor is the corresponding code using pointers directly instead of references) because scoped enums aren't related to their underlying primitives via inheritance.

I could use reinterpret_cast , which, from some preliminary testing, appears to work (and I can't think of any reason why it wouldn't work), but that seems to be frowned upon in C++.

Is there a "standard" way to do this?

I could use reinterpret_cast , which, from some preliminary testing, appears to work (and I can't think of any reason why it wouldn't work), but that seems to be frowned upon in C++.

Indeed, that reinterpret_cast is undefined behavior by violation of the strict aliasing rule.

Eliminating a single mov instruction (or otherwise, more or less, copying a register's worth of data) is premature micro-optimization. The compiler is likely to be able to take care of it.

If performance is really important, then follow the optimization process: profile, disassemble, understand the compiler's interpretation, and work together with it within the defined rules.

At a glance, you (and the compiler) might have an easier time with functions like T get_value() instead of void set_value(T) . The flow of data and initialization make more sense, although type deduction is lost. You can regain the deduction through tag types, if that's really important.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM