简体   繁体   English

通过引用修改范围枚举

[英]Modifying scoped enum by reference

I am increasingly finding scoped enums unwieldy to use. 我越来越多地发现使用范围难以使用的enums。 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: 但是,我没有看到如何在不引入多个临时值的情况下编写模板化版本的set_value

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 . 我相信除了raw_val之外, static_cast引入了第二个临时值。 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. 我认为编译器可能会优化其中的一个或两个,并且在任何情况下它都不应该在性能方面产生太大的影响,因为set_value调用也会生成临时值(假设它没有内联),但这似乎仍然不够优雅。 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++. 我可以使用reinterpret_cast ,从一些初步测试看起来似乎有效(我想不出任何原因导致它不起作用),但这似乎在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++. 我可以使用reinterpret_cast ,从一些初步测试看起来似乎有效(我想不出任何原因导致它不起作用),但这似乎在C ++中不受欢迎。

Indeed, that reinterpret_cast is undefined behavior by violation of the strict aliasing rule. 实际上, reinterpret_cast是违反严格别名规则的未定义行为。

Eliminating a single mov instruction (or otherwise, more or less, copying a register's worth of data) is premature micro-optimization. 消除单个mov指令(或者或多或少,复制寄存器的数据)是过早的微优化。 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) . 乍一看,您(和编译器)可能更容易使用T get_value()等函数而不是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. 如果这非常重要,您可以通过标签类型重新获得扣除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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