【问题标题】:Trying to combine flags within enum value尝试在枚举值中组合标志
【发布时间】:2018-06-07 01:17:19
【问题描述】:

尝试构造一个简单的枚举来包含一组 ios:: 标志以便于引用、参数传递等。我希望能够进行调用:

resultCode = DoSomething(param, TRUNCATE);

ResultCode DoSomething(int param, FileOperation_t operation) {...}

我已经这样定义了我的枚举:

typedef enum {
    TRUNCATE = std::ios::out | std::ios::trunc,
    APPEND   = std::ios::out | std::ios::app
} FileOperation_t;

编译结果:

error: calls to overloaded operators cannot appear in a constant-expression
     TRUNCATE = std::ios::out | std::ios::trunc,
                                          ^

我不明白这个错误是什么意思。我在这里做错了什么,我该如何完成我想做的事情?

gcc (GCC) 4.8.5 20150623(红帽 4.8.5-28)

【问题讨论】:

  • 你使用的是什么编译器/版本?
  • @NathanOliver 在 gcc 上转载到版本 5.5,从 6.1 开始很好
  • 标准说值的类型是实现定义的,你确定是整数吗?

标签: c++ enums


【解决方案1】:

您的编译器似乎默认使用-std=c++98。改用-std=c++11 标志,代码将编译。

在 C++98 中,函数调用(包括重载的操作符调用)不允许在编译时常量表达式中使用(因为没有 constexpr 语义)。


虽然,按照标准编译并不是必需,即使有标志:

This page 表示 std::ios::openmode 是实现定义类型的 typedef,满足 BitmaskType 概念。

虽然 BitmaskType 必须为 &| 等提供运算符重载,但不能保证这些运算符是 constexpr,也不能保证类型本身可以转换为整数类型。

为了获得最大的兼容性,请改用普通的 const 变量:

const std::ios::openmode TRUNCATE = std::ios::out | std::ios::trunc;
const std::ios::openmode APPEND   = std::ios::out | std::ios::app;

(如果您不能使用更新的标准,此解决方案也适用于 C++98。)

【讨论】:

  • 如果重载的运算符不能出现在常量表达式中,那么这个答案如何解决这个问题? TRUNCATE 不是常数吗?不是 TRUNCATE = std::ios::out | std::ios::trunc 一个常量表达式?
  • @Displayname 这里的“常量表达式”可能意味着“编译时常量表达式”。您可以使用非常量表达式初始化 const 变量。但事实证明,问题不是由 typedef 实现不佳引起的,而是由缺少 -std=c++11 标志引起的。
  • 我不能使用 C++11.. 目前我们还坚持使用 C++98。此外,我无法使用 auto 关键字。我必须#include <ios> 然后const std::ios_base::openmode TRUNCATE = std::ios::out | std::ios::trunc;
  • 我仍然不清楚错误的含义..我重载了哪个运算符(据我所知,我没有)以及这里告诉我的错误是什么?
  • @Jon 1) 标准库为std::ios_base::openmode 重载|。 2) 枚举器值必须是编译时常量。但函数调用不能用于编译时常量表达式(C++11 constexpr 函数调用除外)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多