使用模板函数初始化 constexpr 数组
Initialize constexpr array with template functions
我正在尝试为我的模拟器创建一个带有预编译处理程序函数的constexpr std::array
。下面的代码适用于较小的数字,如0x250
,但是当与最新版本的MSVC一起使用时,上述所有内容都会导致"C1026解析器溢出,程序太复杂"。
#include <array>
#include <iostream>
template<typename T>
using Executor = void(*)(T);
using IntExecutor = Executor<int>;
template<int arg>
void func(int value)
{
std::cout << (arg * value) << std::endl;
}
// Static for https://codereview.stackexchange.com/a/173570/160845
template<typename T, T Begin, class Func, T ...Is>
constexpr void static_for_impl(Func&& f, std::integer_sequence<T, Is...>)
{
(f(std::integral_constant<T, Begin + Is>{ }), ...);
}
template<typename T, T Begin, T End, class Func>
constexpr void static_for(Func&& f)
{
static_for_impl<T, Begin>(std::forward<Func>(f), std::make_integer_sequence<T, End - Begin>{ });
}
template<int N>
constexpr std::array<IntExecutor, N> makeLut()
{
std::array<IntExecutor, N> lut = { };
static_for<size_t, 0, N>([&](auto x) {
lut[x] = func<x>;
});
return lut;
}
// 0x250 works just fine
// 0x300 causes a "C1026 parser overflow, program too complex" error
constexpr auto lut = makeLut<0x250>();
int main(int argc, char* argv[])
{
int instruction = 0xDEADBEEF;
int instructionHash = instruction & 0x24F;
lut[instructionHash](instruction);
return 0;
}
我需要一个大小为0x1000
的std::array
.我可以通过使用从0
到0x250
的4
较小的static_for()
循环来实现这一点,但我觉得这是一个丑陋的解决方案。
有没有人知道用模板函数填充constexpr std::array
的正确方法?
您是否尝试过基于std::make_index_sequence
/std::index_sequence
的解决方案?
template <std::size_t ... Is>
constexpr std::array<IntExecutor, sizeof...(Is)>
makeLutHelper (std::index_sequence<Is...>)
{ return { func<int(Is)>... }; }
template <std::size_t N>
constexpr auto makeLut ()
{ return makeLutHelper(std::make_index_sequence<N>{}); }
我无法使用 MSVC 测试它,但是在我的 Linux 平台中,g++ 和 clang++ 也可以编译(需要很长时间)
constexpr auto lut = makeLut<0x10000u>();
我已经修改了 max66 发布的代码,以允许使用自定义 lamdba 函数创建 constexpr 数组。我只是把它贴在这里,以防有人需要它。
#include <array>
#include <iostream>
template<typename T>
using Executor = void(*)(T);
using IntExecutor = Executor<int>;
template<int arg>
void exec(int value)
{
std::cout << (arg * value) << std::endl;
}
template<int value>
constexpr IntExecutor emitExecutor()
{
return exec<value>;
}
template<typename T, class Func, std::size_t ...Is>
constexpr std::array<T, sizeof...(Is)> makeArrayImpl(Func&& func, std::index_sequence<Is...>)
{
return { func(std::integral_constant<std::size_t, Is>{})... };
}
template<typename T, std::size_t N, class Func>
constexpr std::array<T, N> makeArray(Func&& func)
{
return makeArrayImpl<T>(std::forward<Func>(func), std::make_index_sequence<N>{});
}
constexpr auto executors = makeArray<IntExecutor, 0x1000>([&](auto x) {
return emitExecutor<static_cast<int>(x)>();
});
int main(int argc, char* argv[])
{
for (const auto& executor : executors)
{
executor(10);
}
return 0;
}
相关文章:
- 多成员Constexpr结构初始化
- Constexpr替代了新的放置方式,可以让内存中的对象保持未初始化状态
- 当一个值是非常量但用常量表达式初始化时使用constexpr
- 使用 std::分配器在 constexpr 中进行默认初始化
- C++:初始化 constexpr 构造函数中的成员数组
- 初始化模板化类中的静态 constexpr 成员
- 在 constexpr 构造函数中初始化数组是否合法?
- 错误:constexpr 变量'struct2Var'必须由常量表达式初始化
- 静态 constexpr 成员变量初始化
- 全局和局部变量初始化与 constexpr 的差异背后的基本原理
- 正在初始化函数指针的constexpr数组
- 使用 constinit 变量初始化 constexpr 变量
- 这是通过初始化 constexpr 变量来标记编译错误的合理跳转
- 是否可以以编程方式初始化 constexpr std::array 成员
- 使用模板函数初始化 constexpr 数组
- 如何编写工厂功能以在C 中初始化constexpr参考
- 现代C++:初始化 constexpr 表
- 为什么我不能使用 constexpr 全局变量来初始化 constexpr 引用类型
- 使用const初始化constexpr,--int vs float
- 在MSVC和GCC上声明和初始化constexpr的通用语法