GCC 3.3 具有类似于 GCC 3.4 的静态常量变量
Having static const variables with GCC 3.3 similar to GCC 3.4
当使用g ++ 3.4.6(ld 2.15.92.0.2)时,我可以写:
class ConstantContainer {
public:
static const uint16_t MyConstant1 = UINT16_C(0x4321);
static const uint32_t MyConstant2 = UINT32_C(0x87654321);
static const uint64_t MyConstant3 = UINT64_C(0xF0E1D2C3B4A59687);
static const double MyConstant4 = 1.0 / 4.0;
};
并且几乎在任何地方都使用 ConstantContainer::MyConstant1
和其他作为作用域文本的 cheep 替代品,除了初始化其他常量。
但是,当使用 g++ 3.3.6(ld 版本为 2.15.92.0.2,尽管不是相同的二进制文件和发行版)时,代码也可以很好地编译,但在某些情况下,由于在任何时候使用"常量"的未解析引用,链接都会失败:
g++ -o myapp module1.o module2.o ... main.o
moduleN.o(.text+0x59e): In function `BlahBlah(const FooBar&)':
: undefined reference to `ConstantContainer::MyConstant1'
我无法弄清楚引发这种行为的独特功能。例如,不兼容的情况可能如此简单:
class GraphConversionState {
public:
struct NodeIndex {
public:
typedef CxxStd::uint32_t ValueType;
ValueType Value;
class ValueSpecial {
public:
static CxxConstExpr ValueType
Unknown = UINT32_C(0xFF000000),
Isolated = UINT32_C(0xFF111111),
Connected = UINT32_C(0xFFCCCCCC);
};
};
};
也就是说,只有一小堆 uint 类型的静态常量成员,但它们不符合被视为命名文字的条件;同时,在其他情况下,即使是浮点值也可以。唯一明显的区别是作用域级别(类嵌套),但在简化示例的一般情况下,这并不是真正的原因。
显而易见的解决方法是将上述类变成怪物:
class ConstantContainerType {
public:
uint16_t MyConstant1;
uint32_t MyConstant2;
uint64_t MyConstant3;
double MyConstant4;
ConstantContainerType() :
MyConstant1(UINT16_C(0x4321)),
MyConstant2(UINT32_C(0x87654321))
MyConstant3(UINT64_C(0xF0E1D2C3B4A59687))
MyConstant4(1.0 / 4.0)
{ }
};
static const ConstantContainerType ConstantContainer;
// in ConstantContainer.cpp:
const ConstantContainerType ConstantContainer;
但这非常丑陋,不太干净,更容易出错,因为常量和容器类的数量很高。更重要的是,虽然就地声明和定义的常量可能被优化为真正的文字,但在成为单例对象的一部分时,它们是否会被这样处理是非常值得怀疑的。
所以我想知道:GCC 3.3 及更高版本使用哪些确切规则将一些静态 const POD 声明视为常量定义?
你可以在其他地方定义它,
class ConstantContainer {
public:
static const uint16_t MyConstant1;
static const uint32_t MyConstant2;
};
ConstantContainer::MyConstant1 = UINT16_C(0x4321);
ConstantContainer::MyConstant2 = UINT32_C(0x87654321);
或者通过将成员声明为常量来使第二个更干净。
class ConstantContainer {
public:
const uint16_t MyConstant1;
const uint32_t MyConstant2;
ConstantContainer(uint16_t foo, uint16_t bar)
:MyConstant1(foo), MyConstant2(bar)
{}
};
老把戏仍然有效:
class ConstantContainer {
public:
enum { MyConstant1 = UINT16_C(0x4321) };
enum { MyConstant2 = UINT32_C(0x87654321) };
};
当然,如果你想要 uint16_t/uint32_t
型的实际物体 ,它们必须住在某个地方。
只需使用命名空间,而不是像这样滥用类:
namespace ConstantContainer {
uint16_t const MyConstant1 = UINT16_C(0x4321);
uint32_t const MyConstant2 = UINT32_C(0x87654321);
}
此外,命名空间范围内的常量默认具有内部链接(如命名空间级别的静态对象),因此您可以在头文件中声明和定义它们,而不会有违反 ODR 的风险。
相关文章:
- 使用gcc从静态链接的文件中查找可选符号
- 如何使用 GCC 编译器优化创建静态库?
- GCC:--静态链接到pthread的整个存档配方在最近的GCC版本中停止工作
- GCC:在调试构建中优化的静态数据成员
- thread_local静态成员模板定义:初始化失败,GCC
- 将静态库链接到 gcc Linux 中的动态实验室
- 使用 GCC 的静态和动态链接
- GCC 允许访问私有静态成员
- GCC 升级导致模板函数的静态局部变量变得未知
- 为什么 gcc 7.3 接受静态定义中的'this'?
- C 11螺纹 - 非静态成员功能的使用无效 - 工作GCC 5.1.0损坏的GCC 7.3.1
- C++ MinGW GCC CodeBlocks静态链接
- GCC vs CLANG:除了静态强制转换时在未使用的模板专用化中解析外,否
- 模板类中的静态功能:GCC与VS
- GCC静态分析仪(WEFFC ):排除目录
- 如何将GCC中的静态库与其他动态库链接
- 可以从静态库中使用GCC内联函数
- gcc 和 clang 中 constexpr 静态成员变量的链接器错误
- 从成员变量访问静态 constexpr 成员,GCC 错误?
- C++11:GCC 4.8 静态thread_local std::unique_ptr 未定义的引用