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

时间:2015-01-26 13:47:29

标签: c++ compiler-errors constants static-members c++98

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

// 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
};

我该如何避免它们?

2 个答案:

答案 0 :(得分:4)

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

double control[A::someNumber]需要编译时可评估,A::someNumber定义位于不同的翻译单元中。这就是你的编译器所抱怨的。

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

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

答案 1 :(得分:2)

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

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

#include "A.h":确定它包含const static int someNumber; someNumber是一个const int,它的值将在链接时给出

std::bitset<A::someNumber> btst:确定一个bitset,大小为A::someNumber,它被声明为一个const int,直到这里很好......但是哇,编译器不知道const的值那时候 !我们假设它是0 =&GT;并且你得到两个错误,因为编译器无法知道A::someNumber的未来值!

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

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

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

修改

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

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