如何在类命名空间中使用常量作为数组和模板参数

How to use constant in class namespace as the array and template parameters?

本文关键字:数组 参数 常量 命名空间      更新时间:2023-10-16

我想使用类命名空间中的常量作为静态数组的大小和另一个类中的模板参数。我有以下错误

// MS VS 2010 C++98
// A.h
class A
{
public:
 const static int someNumber;
};
// A.cpp
#include <A.h>
const int  A::someNumber = 5;
// B.h
#include <A.h>
class B
{
  std::bitset<A::someNumber> btst; // Error! C2975: '_Bits' : invalid template argument 
  double control[A::someNumber];   // Error! C2466: cannot allocate an array of constant size 0
};

我怎样才能避免它们?

在 C++98 中,您不能使用 constexpr,因为它直到 C++11 才引入。

double control[A::someNumber]需要编译可评估,并且您对A::someNumber的定义驻留在不同的翻译单元中。这就是编译器所抱怨的。

但是,您可以使用enum .我从模板元编程中使用的习语中借用了这种技术:

class A
{
public:
    enum {someNumber = 5};
}; /*and note this semicolon*/

你的问题不是那么简单,因为如果你把所有的声明放在一个文件中,它将正确编译和运行。

但是只要看看编译器在编译 B.h 时可以看到什么(假设它包含在 main.cpp 或 B.cpp 中):

#include "A.h":好的,它包含const static int someNumber; someNumber 是一个常量整数,其值将在链接时给出

std::bitset<A::someNumber> btst :好的,一个位集,大小是A::someNumber,它被声明为常量整数,直到这里很好......但是哇,当时编译器不知道常量的值!假设它是 0=> 并且您会收到两个错误,因为编译器无法知道A::someNumber的未来值!

现在我们知道,修复很简单:只需在 A.h 中写:

const static int someNumber = 5; // valid for a litteral const

因为现在编译器在编译时知道A::someNumber的值,并且可以正确编译包括 B.h 在内的文件。

编辑

您可能会对用A.h编写const static int someNumber = 5;的想法感到害怕,因为它可以包含在许多编译单元中,并且您不想在许多单元中定义相同的常量。但实际上这不是问题:

  • 在编译时,编译器随时使用A::someNumber的值。它指出类 A 包含一个名为 someNumber 的静态字段。
  • 在链接时,链接器确保只有一个A::someNumber实例。您可以通过打印来自不同编译单元的静态 const 字段的地址来控制它,您将获得相同的值......除非你的开发工具严重损坏!