让我首先说明我的意图。在较早的(C ++)时代,我们将有如下代码:
class C
{
public:
enum {SOME_VALUE=27};
};
然后,我们可以SOME_VALUE
在整个代码中将其用作编译时间常数,并且无论编译器看到什么C::SOME_VALUE
,它都只会插入文字27。
现在,将代码更改为以下内容似乎是可以接受的:
class C
{
public:
static constexpr int SOME_VALUE=27;
};
SOME_VALUE
从C ++ 11开始,这看起来更加简洁,给出了定义良好的类型,似乎是首选方法。(至少对我来说是SOME_VALUE
无法预料的)问题是,这还会导致需要将其置于外部的情况。也就是说,在某些cpp文件中,我们需要添加:
constexpr int C::SOME_VALUE; // Now C::SOME_VALUE has external linkage
导致这种情况的原因似乎是在使用const引用时SOME_VALUE
,这种情况在C ++标准库代码中经常发生(请参阅此问题底部的示例)。顺便说一下,我正在使用gcc 4.7.2作为我的编译器。
由于这一难题,我不得不回到定义SOME_VALUE
为枚举(即旧派)的方式,以避免为某些但不是全部静态constexpr成员变量向cpp文件中添加定义。难道没有什么办法告诉编译器这constexpr int SOME_VALUE=27
意味着SOME_VALUE
应该仅将其视为编译时常数,而不应将其视为具有外部链接的对象吗?如果看到与它一起使用的const引用,请创建一个临时引用。如果您看到它的地址,那么就需要生成一个编译时错误,因为这是一个编译时间常数,仅此而已。
以下是一些看似良性的示例代码,这些代码使我们需要SOME_VALUE
在cpp文件中添加的定义(再次,用gcc 4.7.2测试):
#include <vector>
class C
{
public:
static constexpr int SOME_VALUE=5;
};
int main()
{
std::vector<int> iv;
iv.push_back(C::SOME_VALUE); // Will cause an undefined reference error
// at link time, because the compiler isn't smart
// enough to treat C::SOME_VALUE as the literal 5
// even though it's obvious at compile time
}
在文件范围的代码中添加以下行将解决该错误:
constexpr int C::SOME_VALUE;
SOME_VALUE
……的地址,我被迫退回到定义SOME_VALUE
为enum
”。枚举数是prvalue,您也不能使用它们的地址。