c++ - 如何将字符串列表存储在 constexpr 上下文中?
问题描述
我正在为某些域对象类转换这些文档字符串表(作为像系统这样的类型特征),直到我偶然发现这个问题。后来,我计划在编译时检查这些特殊成员是否编写了文档(作为我为什么在编译时想要它的理由)。我创建了一个小示例进行演示:
#include <initializer_list>
struct CStr {
struct M {
const char* name;
const char* val;
};
constexpr CStr(const std::initializer_list<M>& str) : str_(str) {
};
std::initializer_list<M> str_;
};
constexpr CStr cstr_test{ { {"key", "val"} } };
int main() {
return cstr_test.str_.begin()->name[0];
}
基本上 3 个主要编译器似乎对这种情况有不同的处理方式,这似乎适用于较旧的gcc,但在更改为最新版本 9.1 时无法编译(说 cstr_test 行不是一个常量表达式)。在msvc(和我感兴趣的那个)上initializer_list
,大小正确,但临时文件无法保存到输出。clang拒绝编译,因为临时创建了。最后一件事似乎是一个提示,我怀疑这也是msvc可能发生的事情,但没有发出错误。
std::initializer_list<M>
如果将示例更改为 just ,则可以修复该示例M
。
参考资料中的相关部分可能是:
底层数组是一个 const T[N] 类型的临时数组,其中每个元素都是从原始初始化列表的相应元素复制初始化的(除了缩小转换无效)。底层数组的生命周期与任何其他临时对象相同,只是从数组初始化一个 initializer_list 对象可以延长数组的生命周期,就像将引用绑定到临时对象一样(有相同的例外,例如初始化非-静态类成员)。底层数组可以分配在只读存储器中。
如何在编译时创建包含字符串的对象列表?
解决方案
std::initializer_list
不应该用作存储。
因此,在您的情况下,应该在课堂之外进行存储。常规 C 数组或std::array
可用于此。
然后你的班级可能只看到这些数据。
C++20 提供std::span
.
在 C++20 之前,您可能会执行以下操作:
struct CStr {
struct M {
const char* name;
const char* val;
};
constexpr CStr(const M* data, std::size_t size) : data(data), size(size) {}
const M* begin() const { return data; }
const M* end() const { return data + size; }
const M* data;
std::size_t size;
};
constexpr CStr::M data[]{ { {"key", "val"} } };
constexpr CStr cstr_test(data, 1);
int main() {
return cstr_test.begin()->name[0];
}
推荐阅读
- ruby-on-rails - 多对多关联通过另一个关联
- javascript - 如何在gridComplete之后过滤数据 - 客户端(jqGrid)
- c++ - 是否可以将纯虚函数覆盖到模板?
- node.js - 在本地存储文件的位置,以便在删除 Electron 应用程序后不会被删除?
- mongodb - 从 mongodb 中的第三级嵌套数组文档中查找计数
- c++ - 关于封装的 C++ 迭代节点
- api - 贝宝获得客户批准流程不明确
- angularjs - 无法将模态数据输入 angularjs 控制器
- javascript - 应用程序脚本 new Date 和 getTime 在浏览器中的行为不一样
- java - 在大文件中查找重复项和排列