提问人:Typhaon 提问时间:11/2/2022 最后编辑:wovanoTyphaon 更新时间:11/11/2022 访问量:149
如何创建不可变结构的 std::array ?即只有 const 值的结构 [duplicate]
How do I create an std::array of immutable structs? I.e. structs with only const values [duplicate]
问:
这个问题在这里已经有答案了:
在编译时以算法初始化 std::array (3 个答案)
在编译时使用 Constexpr 填充数组 (4 个答案)
将大小为编译时常量的数组初始化为单个值 (3 个答案)
去年关闭。
这篇文章是去年编辑并提交审查的,但未能重新打开该帖子:
原始关闭原因未解决
假设我有结构体 S:
struct S {
const int i;
const bool b;
}
我想创建这个结构的(非常量)数组,如下所示:
std::array<S, 16> arr;
for(int i = 0; i<arr.size(); i++)
arr[i] = { i, i%2==0 };
然后编译器会抱怨我在初始化数组时没有初始化 a const 变量。
我尝试用向量作为中介来做。但是在我正在编写的函数中,我必须在另一个结构中传递原始数组,并返回另一个结构。
struct OtherStruct {
const std::array<S,16> sArray;
};
OtherStruct f() {
std::vector<S> vec(16);
for(int i = 0; i<16; i++)
vec.push_back({ i, i%2==0 });
return { vec.data() };
}
但这也没有用。我希望将指向向量数据的指针转换为 C 样式的数组,从中可以创建 std::array。解决这个问题的最干净的方法是什么?
我正在使用 C++11。
请注意,此示例是粗略的简化。该行将被解析传入网络数据的函数所取代。实际数组要大得多,结构也更复杂。在编译时,将填充结构的任何数据都不会被知道,只有布局。arr[i] = { i, i%2==0 };
答:
2赞
Caleth
11/2/2022
#1
您可以使用参数包扩展来创建任意大小的初始化程序列表。
您需要向后移植到 C++11std::index_sequence
template <size_t... Is>
std::array<S, sizeof...(Is)> make_s_array_impl(index_sequence<Is...>) {
return { { { Is, Is % 2 == 0 }... } };
}
template <size_t N>
std::array<S, N> make_s_array()
{
return make_s_array_impl(make_index_sequence<N>{});
}
1赞
VLL
11/2/2022
#2
由于值的数量在编译时是已知的,因此可以使用初始值设定项列表填充数组。您可以使用以下BOOST_PP_REPEAT
轻松创建它:
#include <boost/preprocessor/repetition/repeat.hpp>
struct S {
const int i;
const bool b;
};
struct OtherStruct {
const std::array<S,16> sArray;
};
OtherStruct f() {
#define FILL(z, i, ignored) { i, i%2==0 },
return {std::array<S,16>{{
BOOST_PP_REPEAT(16, FILL, ignored)
}}};
#undef FILL
}
-1赞
Gio
11/2/2022
#3
在 C/C++ 中,当您使用关键字时,您不能在声明变量时保持未初始化状态,并且在声明后也不能分配新值。const
例如:
const int i = 5; //this is a correct way to use the const keyword
const int i;
...
i = 5; //this is NOT a correct way to use the const keyword
但是,您可以使用将相同类型的指针绑定到结构实例的值,并在 for 循环中仅更改一次。const_cast<T>
通过这种方式,您可以获得您所要求的。
#include <iostream>
#include <array>
struct S{
const bool b = 0; //Intialize the values in order to avoid compiler errors.
const int i = 0;
};
int main(){
std::array<struct S, 16> arr;
for(int i = 0; i<arr.size(); i++){
// declare a variable that point to the const value of your struct instance.
bool* b = const_cast <bool*> (&arr[i].b);
int* in = const_cast <int*> (&arr[i].i);
*b = i; //change the value with the value you need.
*in = i%2==0;
}
for(int i = 0; i<arr.size(); i++){
int a = i%2==0;
std::cout<< "const bool: " << arr[i].b << " " << (bool)i << "const int: " << arr[i].i << " " << a << std::endl;
}
}
评论
0赞
Typhaon
11/2/2022
这是行不通的,因为编译器会抱怨 因为那是它初始化所有内容的那一刻,而 const 变量没有默认初始化std::array<struct S, 16> arr;
0赞
Fareanor
11/2/2022
更重要的是,使用来修改对象是一种一致性违规和未定义的行为。这不是 的预期用途。永远不要这样做。const_cast
const
const_cast
评论
std::array<S,16> createAlternatingOnesZeros()
return {vec[0], vec[1], ...
BOOST_PP_REPEAT
const
private
const
const S