我对静态积分常数有一种奇怪的行为:
#include <iostream>
#include <inttypes.h>
class Test{
public:
static const uint32_t Magic = 0x1123;
};
class DataStream{
public:
template<typename T>
DataStream& operator <<( const T& value )
{
std::cout << value << std::endl;
return *this;
}
};
int main()
{
DataStream s;
uint32_t a = Test::Magic; // ok
bool compare = ( a == Test::Magic ); // ok
s << compare;
s << a;
s << Test::Magic; // fail
return 0;
}
我知道这些常量应该在.cpp之外的类中定义为
const uint32_t Test::Magic;
但奇怪的是,上面的代码可以正常使用行s << Test::Magic;
,并且仅当Magic
直接与模板operator <<
一起使用时才会产生错误。
更多错误undefined reference to 'Test::Magic'
与GCC
一起显示,但与MSVC
不一致。
问题是为什么我应该在课外定义Test::Magic
(即使没有价值!!!),为什么我的代码在某些条件下工作正常,即使没有这样的定义?
答案 0 :(得分:2)
通常,如果它们是ODR used,则应在.cpp文件中定义所有静态const名称。参考这个论点是ODR using
他们。但是,违反此规则是未定义的行为,并且MSVC不报告错误只是未定义行为可以表现的方式之一。
作为一个实际考虑因素,当函数未内联时,您可能会遇到错误,并且可能无法查看内联函数。我的猜测是内联的工作方式与您用于这些编译器的优化级别不同。
答案 1 :(得分:1)
§9.4.2静态数据成员[class.static.data]
如果非易失性const静态数据成员是整数或枚举类型,则其在类定义中的声明可以指定 支撑或平等初始化器[...] 如果成员使用,则仍应在命名空间范围内定义 (3.2)在程序和命名空间范围定义中不得 包含初始化程序。
- 醇>
[注意:程序中有一个静态数据成员的确切的一个定义是odr-used(3.2); 无需诊断。 - 尾注]