如何在常量头文件中声明不同大小列表的编译时常量列表



简介

你好,

我想优化我的应用程序,尤其是一个常量头文件。为了做到这一点,我定义了内联constexpr常量,以避免这些变量在包含它们的文件中有多个副本。还有编译时间常数。

我现在想添加一个新的内联constexpr变量/数组,这会使常量头文件复杂化。我想要一个固定大小的列表/数组,其中包含不同大小的列表或数组。最后,我想要一个简单的使用方法和方便的访问。


计划工作

在下文中,我注意到CONST表示CONST值是编译时常数。我想实现我的常量列表/数组,它们后来需要包含在父列表/数组中(都在常量头文件中定义(,如下所示:

inline constexpr std::array<CONST int, size1> first = { some CONST values };
inline constexpr std::array<CONST int, size2> second= { some other CONST values };
inline constexpr std::array<CONST int, size3> third = { some other CONST values };

现在,如果可能的话,我们的想法是通过父列表访问每个阵列

CONTAINER parent = { first, second, third };

问题

现在,当我想操作数组时,我看到问题出现了。理想情况下,我希望孩子们(第一、第二和第三(表现得像std::vector<int>并且父对象为std::vector<std::vector<CONST int>>。因为我可以通过std::vector<CONST int>*指针和我可以像下面这样更改指向的矢量:

// Initialization
std::vector<CONST int>* current_vec = nullptr;
...
// First assignation
current_vec = parent[0];
...
// Reassignation
current_vec = parent[1];
...

但是这个实现使用vector。对于std::array,我认为我的指针不能做到这一点,因为它需要知道每个子数组的大小。另外,也许我可以用迭代器做一些事情,但同样的问题(auto关键字可能是一个解决方案?(。

所以,我现在所做的是使用std::vector并将子数组定义为:

inline const std::vector<int> first = { some CONST values };
inline const std::vector<int> second = { some other CONST values };
inline const std::vector<int> third = { some other CONST values };

然后,我将父对象定义为:

inline constexpr std::array<const std::vector<CONST int>*, 3> parent = {&first, &second, &third};

我可以访问上面预期的孩子:

const std::vector<CONST int>* to_access = parent[0];

它似乎起作用了,我认为向量是const编译的(我想是的,如果不是,我将无法编译内联constexpr父级?(。


问题

首先,你觉得这种方法有意义吗?是不是有一些我不知道的东西真的让我的解决方案出错了?其次,你会使用另一个容器或另一个带有constexpr的解决方案,而不是const向量,这是我可能不知道的替代方案(可能是constexpr函数或使用迭代器(吗?

我希望一切都清楚。我提前感谢你的建议和帮助。

注意

我知道我们可以从c++20开始定义constexpr向量,但我认为它只适用于msvc c++20编译器,所以我想避免这种解决方案。

以下内容可能会给您带来一些想法:

#include <array>
const int size1 = 1;
const int size2 = 2;
const int size3 = 3;
constexpr std::array<int, size1> first = { 1 };
constexpr std::array<int, size2> second= { 2 };
constexpr std::array<int, size3> third = { 3 };
#include <variant>
// The safest, I guess, annoying to use.
constexpr std::array<
std::variant<decltype(first), decltype(second), decltype(third)>,
3> parent1 = {
first, second, third
};
// The simplest - no bounds information.
constexpr std::array<const int *, 3> parent2 = {
first.data(), second.data(), third.data()
};
// Tie bounds together with pointers.
constexpr std::array<std::pair<const int *, std::size_t>, 3> parent3 = {{
{ first.data(), first.size(), },
{ second.data(), second.size(), },
{ third.data(), third.size(), },
}};
// In C++20 we now have span
#include <span>
constexpr std::array<std::span<const int>, 3> parent4 = {{
first, second, third
}};
// Compile-time template access.
template<int index>
constexpr auto parent5() {
if constexpr (index == 0) {
return first;
} else if constexpr (index == 1) {
return second;
} else if constexpr (index == 2) {
return third;
}
}

我认为统一访问不同大小的3个数组会带来越界问题。记住检查边界以避免未定义的行为。

最新更新