4

我越来越发现范围枚举难以使用。我正在尝试编写一组函数重载,包括一个范围枚举的模板,该模板通过引用设置/初始化一个值——如下所示:

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

但是,我不太明白如何在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);
}

我相信static_cast除了 . 之外还引入了第二个临时值raw_val。我想编译器可能会优化其中一个或两个,并且在任何情况下它都不应该在性能方面产生太大影响,因为set_value调用也会生成临时值(假设它不是内联的),但是这似乎仍然不优雅。我想做的是这样的:

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

...但是这是无效的(相应的代码也不是直接使用指针而不是引用),因为作用域枚举与它们的底层原语通过继承无关。

我可以使用reinterpret_cast,从一些初步测试来看,它似乎可以工作(而且我想不出它为什么不工作的任何原因),但这似乎在 C++ 中不受欢迎。

有没有“标准”的方式来做到这一点?

4

1 回答 1

0

我可以使用reinterpret_cast,从一些初步测试来看,它似乎可以工作(而且我想不出它为什么不能工作的任何原因),但这似乎在 C++ 中不受欢迎。

实际上,这reinterpret_cast是违反严格别名规则的未定义行为。

消除单个mov指令(或或多或少地复制寄存器的数据)是过早的微优化。编译器很可能能够处理它。

如果性能真的很重要,那么遵循优化过程:分析、反汇编、理解编译器的解释,并在定义的规则内与它一起工作。

乍一看,您(和编译器)可能会更轻松地使用诸如T get_value()代替void set_value(T). 数据流和初始化更有意义,尽管类型推导丢失了。如果这真的很重要,您可以通过标签类型重新获得扣除。

于 2015-05-15T03:04:22.190 回答