【问题标题】:Using typed constant as array size in C++ header在 C++ 标头中使用类型化常量作为数组大小
【发布时间】:2016-07-07 09:03:38
【问题描述】:

我有一个头文件,声明常量如下:

// foo.h
const unsigned FOO_BUFFER_SIZE = 8;
const unsigned FOO_NUM_BUFFERS = 4;

class FooSource {
    ...
    char buffer[FOO_BUFFER_SIZE];
    ...
};

class FooSink {
    ...
    void ProcessBuffer(char *buffer);
    ...
};

不幸的是,这有时会在不使用 FOO_NUM_BUFFERS 的编译单元中产生未使用的变量警告。避免警告的公认方法如下:

// foo.h
extern const unsigned FOO_BUFFER_SIZE;
extern const unsigned FOO_NUM_BUFFERS;
...

// foo.cc
const unsigned FOO_BUFFER_SIZE = 8;
const unsigned FOO_NUM_BUFFERS = 4;

但这会导致FOO_BUFFER_SIZE 出现array bound is not an integer constant 警告。我可以为这两个常量使用不同的样式,但我更喜欢一致的样式。

使用#define 会起作用,但会失去类型化常量的好处。将常量移到其中一个类中也可以,但不清楚哪个类应该“拥有”常量,因为它们都被两者使用。

有没有更好的方法来定义这些常量?

编辑:警告只在奇怪的情况下出现 - 通常 const 样式是可以的

具体来说,当文件中存在不相关的编译错误时会出现警告,并且使用内联函数的值初始化常量:

static inline unsigned f(unsigned x) {
    return x;
}

const unsigned FOO_CONSTANT = f(4);

class Foo {
    Foo() { create_a_compile_error; };
};

使用g++ -Wall 提供以下编译器输出:

In file included from foo.cc:2:0:
foo.h: In constructor ‘Foo::Foo()’:
foo.h:10:13: error: ‘create_a_compile_error’ was not declared in this scope
     Foo() { create_a_compile_error; };
             ^
foo.h: At global scope:
foo.h:7:16: warning: ‘FOO_CONSTANT’ defined but not used [-Wunused-variable]
 const unsigned FOO_CONSTANT = f(4);
                ^

由于我不能轻易地将内联函数更改为更合理的东西,我认为在这种情况下抑制警告是正确的方法。

【问题讨论】:

  • 如果该常量在唯一的类中使用,则可以将其作为静态常量添加到该类中。
  • 不知道是不是你真正想要的东西,不过你也可以用枚举来定义这样一个常量。
  • “这有时会在不使用常量的编译单元中创建未使用的变量警告。”为什么?不是在foo.h 中声明的类FooSource 使用了const 吗?
  • 如果您有 C++11 编译器,则将其设为 staticconstexpr
  • " 这有时会在不使用常量的编译单元中创建未使用的变量警告" - 如果变量用于数组,如何“未使用”尺寸?请发布一段重现警告的代码,以及有关您的编译器的更多信息。

标签: c++


【解决方案1】:

首先,最好的选择是将变量移动到更细粒度的标题中,也许是FooBuffer.hpp

如果这不可行,您可以使用 __attribute__((unused))(gcc 和 clang)抑制单个变量的警告:

const unsigned FOO_BUFFER_SIZE __attribute__((unused)) = 8;

如果 Boost 可用,您可以使用 BOOST_ATTRIBUTE_UNUSED(自 1.57 起)。

与任何警告抑制一样,您应该记录警告被抑制的原因,以便在这些条件发生变化时可以移除抑制(可能还有变量)。

【讨论】:

  • 从 C++17 开始,attribute [[maybe_unused]] 也可用。最新版本的 GCC 和 Clang 应该已经有了。
【解决方案2】:

无需使用特定于编译器的扩展,例如 __attribute__((unused))

只需在标题中添加一个typedef

const unsigned FOO_NUM_BUFFERS = 4;
typedef char FOO_buffer[FOO_NUM_BUFFERS];

编译器很少对未使用的类型定义发出警告,因为这会在使用标准头文件时引起大量警告(这对开发人员来说非常不受欢迎)。但是,对于大多数编译器,这确实会导致编译器将 FOO_NUM_BUFFERS 识别为正在使用。

【讨论】:

    猜你喜欢
    • 2019-12-28
    • 1970-01-01
    • 2011-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    相关资源
    最近更新 更多