如何使用 class 命名空间中的常量作为数组和模板参数?
How to use constant in class namespace as the array and template parameters?
我想使用 class 命名空间中的常量作为静态数组的大小和另一个 class 中的模板参数。我有以下错误
// 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 是一个 const int,它的值将在 link 时间
给出
std::bitset<A::someNumber> btst
:好的位集,大小是 A::someNumber
,它被声明为一个 const int,直到这里都很好......但是哇,const 的值是未知的当时的编译器!让我们假设它是 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;
因为它可能包含在许多编译单元中并且您不想 define 许多单位的相同常数。但实际上这不是问题:
- 在编译时,编译器会在需要时随时使用
A::someNumber
的值。它注意到 class A 包含 one 静态字段,名为 someNumber
.
- 在link时,linker确保
A::someNumber
只有一个实例。您可以通过打印来自不同编译单元的静态常量字段的地址来控制它,您将获得相同的值......除非您的开发工具严重损坏!
我想使用 class 命名空间中的常量作为静态数组的大小和另一个 class 中的模板参数。我有以下错误
// 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 是一个 const int,它的值将在 link 时间
std::bitset<A::someNumber> btst
:好的位集,大小是 A::someNumber
,它被声明为一个 const int,直到这里都很好......但是哇,const 的值是未知的当时的编译器!让我们假设它是 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;
因为它可能包含在许多编译单元中并且您不想 define 许多单位的相同常数。但实际上这不是问题:
- 在编译时,编译器会在需要时随时使用
A::someNumber
的值。它注意到 class A 包含 one 静态字段,名为someNumber
. - 在link时,linker确保
A::someNumber
只有一个实例。您可以通过打印来自不同编译单元的静态常量字段的地址来控制它,您将获得相同的值......除非您的开发工具严重损坏!