如何定义在多翻译单元中仅存单实例的constexpr构造数组?
C++14 下 constexpr 类单实例解决方案
针对你遇到的问题——需要在整个项目中保留constexpr类的唯一实例,同时支持constexpr和非constexpr上下文访问,这里提供两种可行的C++14兼容方案:
方案一:模板载体实现单实例
利用C++模板的隐式实例化特性,将constexpr类实例放在模板类的static成员中,确保整个程序中仅存在一个实例,且编译期可直接访问其值。
示例代码:
#include <array> // 你的constexpr类定义 constexpr class MyConstClass { public: std::array<int, 5> data; // constexpr构造函数初始化数组 constexpr MyConstClass() : data{1, 2, 3, 4, 5} {} }; // 模板载体类,默认模板参数确保全局唯一实例 template <typename Dummy = void> class SingletonWrapper { public: // static constexpr成员,类内初始化 static constexpr MyConstClass instance{}; }; // 显式实例化模板(可选,提前实例化避免延迟实例化的潜在问题) template class SingletonWrapper<>; // 定义便捷别名,简化访问 constexpr const MyConstClass& MySingleton = SingletonWrapper<>::instance; // constexpr上下文使用示例 constexpr int CompileTimeVal = MySingleton.data[2]; // 编译期求值为3 // 非constexpr上下文使用示例 void traverse_array() { for (int num : MySingleton.data) { // 运行时遍历数组 } }
原理说明
- 模板类的static成员会根据模板参数唯一实例化,这里使用默认的
void作为模板参数,确保整个程序中仅生成一个instance实例。 - 由于
instance是constexpr且定义在头文件中,编译器在处理constexpr上下文时能直接获取其值;链接阶段,所有翻译单元会共享同一个实例,不会出现重复定义问题。
方案二:constexpr 工厂函数结合静态存储区对象
如果模板方案不符合你的代码风格,可以将constexpr实例放在单个cpp文件中,同时提供一个constexpr函数返回其编译期已知的常量值,非constexpr上下文则直接访问全局实例。
示例代码:
头文件(my_singleton.h)
#include <array> constexpr class MyConstClass { public: std::array<int, 5> data; constexpr MyConstClass() : data{1, 2, 3, 4, 5} {} // 提供编译期访问数组元素的方法 constexpr int get(int idx) const { return data[idx]; } }; // 声明全局实例,供非constexpr上下文使用 extern const MyConstClass MySingleton; // constexpr函数,直接返回编译期已知的数组元素 constexpr int get_singleton_val(int idx) { return MyConstClass{}.data[idx]; }
实现文件(my_singleton.cpp)
#include "my_singleton.h" // 定义全局唯一实例 constexpr MyConstClass MySingleton{};
原理说明
- 对于constexpr上下文,直接通过
get_singleton_val函数构造临时constexpr对象并取值,完全在编译期完成,无需依赖全局实例。 - 非constexpr上下文直接访问
MySingleton,由于其定义在单个cpp文件中,链接时仅存在一个实例,避免重复问题。
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

