c++ - 将枚举数组转换为参数包
问题描述
我正在努力创建一个对象,因为我必须parameter pack
从函数内的数组创建一个新对象。该数组包含几个enum
相同的元素enum
type
。
错误消息指出,该数组不是静态的,因此不是可以转换为参数包的有效输入。
是否有以下可能性:
enum Enums{e1, e2};
template<typename T, auto ...Enums>
class Example{};
template<int size>
constexpr auto createObj(){
Enums enum_array[size] = {};
for(int i = 0; i< size ; i++){
//fill array with e1 and e2
}
return Example<double, enum_array>();
}
错误信息:
error: the address of ‘enum_array’ is not a valid template argument because it does not have static storage duration
return Example<double, enum_array>();
解决方案
您可能需要一些间接级别。首先,要使用任何值作为模板参数,它必须是编译器的编译时间常数,以便编译器实例化模板并生成其代码。
为此,您需要将计算数组的函数放在 constexpr 函数中:
template<int size>
constexpr auto createObjArray() {
auto enum_array = std::array<Enums, size>{};
for(int i = 0; i < size ; i++){
//fill array with e1 and e2
}
return enum_array;
}
然后,您需要一种将数组扩展为包的方法。目前在 C++17(和 C++20)中,它不能在本地完成。您将需要某种索引序列。最直接的方法是使用辅助函数:
template<std::size_t... S>
constexpr auto createObjHelper(std::index_sequence<S...>){
constexpr auto enumArray = createObjArray<sizeof...(S)>();
return Example<double, enumArray[S]...>();
}
然后从一个面向用户的函数中包装所有这些:
template<int size>
constexpr auto createObj(){
return createObjHelper(std::make_index_sequence<size>());
}
请注意,其中许多辅助函数可以使用 lambdas 来实现。例如,一个 lambda 可以有一个 constexpr 主体并在编译时在运行时函数内执行:
template<std::size_t... S>
constexpr auto createObjHelper(std::index_sequence<S...>){
// implicitly constexpr ---v
constexpr auto enumArray = []{
auto enum_array = std::array<Enums, size>{};
for(int i = 0; i < size ; i++){
//fill array with e1 and e2
}
return enum_array;
}();
return Example<double, enumArray[S]...>();
}
在 C++20 中,您可以使用熟悉的 lambda 模板函数语法来避免辅助函数:
template<int size>
constexpr auto createObj(){
// implicitly constexpr ---v
constexpr auto enumArray = []{
Enums enum_array[size] = {};
for(int i = 0; i < size ; i++){
//fill array with e1 and e2
}
return enum_array;
}();
return []<std::size_t... S>(std::index_sequence<S...>) -> decltype(auto) {
return Example<double, enumArray[S]...>();
}(std::make_index_sequence<size>());
}
在 C++23 中,如果批准引入结构化绑定包,则可以删除第二个 lambda,以便直接在函数中创建新包:
template<int size>
constexpr auto createObj(){
// implicitly constexpr ---v
constexpr auto enumArray = []{
Enums enum_array[size] = {};
for(int i = 0; i < size ; i++){
//fill array with e1 and e2
}
return enum_array;
}();
constexpr auto&& [...allEnums] = enumArray;
return Example<double, allEnums...>();
}
推荐阅读
- avisynth - 在avisynth中使用ddcomb插件
- c++ - g++ -I 包含所有带有头文件的子目录
- javascript - 如何在提交反应之前检查多个文本框验证
- nuget - NuGet 版本范围 - 始终获取具有最高修订号的包
- mysql - 与另一个表连接时,即使第一个表为空(并且查询没有 IN),SQL 查询也会返回 null
- javascript - 如何使用 clip-path CSS 属性截取 HTML 节点的屏幕截图?(html2canvas 不适用于此)
- amazon-web-services - 如何让 AWS lambda 将字符串值传递给 s3 存储桶中的 index.html
- css - Angular NgStyle:列表图像样式
- linux-device-driver - 在 Android 上添加对 DSI 面板的支持的工作流程
- javascript - 循环遍历数据对象并将 Header 映射到 React 中的值