目标是将大型数据结构序列化为constexpr
初始化,因此它们将成为.text
or.rodata
段的一部分,并可用于consteval
等constexpr
。
数据结构包含用于交叉引用/索引等的容器。所有这些代码都将生成,因此我们可以使用相同或等效的容器逻辑在代码生成器内计算容器状态,然后按原样序列化容器状态。
C++ 不支持constexpr
.
“在 Kona 2019 中,这种方法被认为过于脆弱,因此非瞬态分配被从功能集中移除。” http://open-std.org/JTC1/SC22/WG21/docs/papers/2019/p0784r7.html
因此,使用std::
或自制动态容器是不可能的。
(可变参数?)模板的使用似乎也是不可能的,因为数据结构必须以运行时动态方式可用,即任何模板的使用都需要在顶部有一个类型擦除层,这看起来很笨拙。见https://www.artima.com/articles/on-the-tension-between-object-oriented-and-generic-programming-in-c
正如这里所探讨的,下一次尝试是尝试序列化为复合文字。请参阅https://en.cppreference.com/w/c/language/compound_literal
标准 C++20 实际上并没有正式支持复合文字,但我们可以依靠编译器扩展来支持 C++ 中的这个 C 特性。似乎在所有主要的 C++ 编译器中都可用。
下面的示例只是一个非常小的概念证明(或尝试这样做)。
问题:以下适用于 Clang 但不适用于 GCC。为什么?有不同的方法吗?
#include <memory>
template <typename K, typename V>
struct Entry{
K key;
V value;
};
template <typename K, typename V>
struct Bucket{
size_t n;
// C++ cannot initialize a flexible array in a struct, use a pointer.
Entry<K, V> *entries;
};
template <typename K, typename V>
struct HashMap{
using bucket_t = Bucket<K, V>;
using entry_t = Entry<K, V>;
size_t n;
// C++ cannot initialize a flexible array in a struct, use a pointer.
bucket_t *buckets;
constexpr V get(K key) const {
const size_t i = key % n;
const auto &bucket = buckets[i];
for (size_t j = 0; j < bucket.n; ++j) {
if (bucket.entries[j].key == key) {
return bucket.entries[j].value;
}
}
return {};
}
};
using MyHashMap = HashMap<int, double>;
constexpr MyHashMap map =
{
2,
// Because we can't initialize a flexible array, we need to employ a so-called
// compound literal and let it decay to a pointer.
(MyHashMap::bucket_t[])
{
{
3,
(MyHashMap::entry_t[]) // dito
{ {0, 1.2}, {2, 2.4}, {6, 3.6} }
},
{
4,
(MyHashMap::entry_t[]) // dito
{ {1, 0.0}, {5, 2.0}, {11, 4.0}, {13, 1.0} }
}
}
};
// Serves as proof of concept by succeeding as consteval.
consteval int proofOfConcept() {
// Should return 76 as a constant,
return 10*(map.get(0) + map.get(11) + map.get(2));
}
int main() {
return proofOfConcept();
}
在 GCC 上,这失败了。
<source>: In function 'int main()':
<source>:94:26: in 'constexpr' expansion of 'proofOfConcept()'
<source>:90:23: in 'constexpr' expansion of 'map.HashMap<int, double>::get(0)'
<source>:94:26: error: the value of '._anon_115' is not usable in a constant expression
94 | return proofOfConcept();
| ~~~~~~~~~~~~~~^~
<source>:84:9: note: '._anon_115' was not declared 'constexpr'
84 | }
| ^
在这里探索它: