Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在constexpr函数中实例化多个模板_C++_Templates_C++17_Template Meta Programming_Constexpr - Fatal编程技术网

C++ 在constexpr函数中实例化多个模板

C++ 在constexpr函数中实例化多个模板,c++,templates,c++17,template-meta-programming,constexpr,C++,Templates,C++17,Template Meta Programming,Constexpr,我正在开发一个游戏机模拟器。出于好奇,我想生成一个包含run()函数指针以及其他一些有用字段的consteprOpcode对象数组 下面是一个大致工作原理的示例: #include <array> struct CPU { int some_state = 0; }; void f(CPU& cpu) { cpu.some_state = 42; } void g(CPU& cpu) { cpu.some_state = 12; } s

我正在开发一个游戏机模拟器。出于好奇,我想生成一个包含
run()
函数指针以及其他一些有用字段的
constepr
Opcode
对象数组

下面是一个大致工作原理的示例:

#include <array>

struct CPU
{
    int some_state = 0;
};

void f(CPU& cpu)
{
    cpu.some_state = 42;
}

void g(CPU& cpu)
{
    cpu.some_state = 12;
}

struct Opcode
{
    using Runner = void(*)(CPU&);
    Runner run = [](CPU&) {};

    /* more fields here */
};

constexpr auto gen_opcodes()
{
    std::array<Opcode, 2> ret {};

    ret[0] = { f };
    ret[1] = { g };

    return ret;
}

constexpr auto opcodes = gen_opcodes();

int main()
{
    CPU cpu;
    opcodes[1].run(cpu);
}
这失败了:

constexpr auto gen_opcodes()
{
    std::array<Opcode, 100> ret {};

    for (int i = 30; i < 50; ++i)
    {
        ret[i] = { f<i> };
    }

    return ret;
}
constexpr自动生成操作码()
{
std::数组ret{};
对于(int i=30;i<50;++i)
{
ret[i]={f};
}
返回ret;
}
注:这显然是为了举例,在实践中略有不同

原因是在这种情况下,
i
不是一个常量表达式

如何在不手工编写的情况下生成这些函数模板?否则,是否有另一种“足够短”且具有我前面所述优点的解决方案

我有一些想法,但似乎都不够:

  • 有状态的兰博达斯。但是,
    std::function
    constepr
    上下文中不起作用,因为它有一个非平凡的析构函数,并且捕获lambda不能强制转换到函数指针中
  • 函数对象。我不知道如何将它们以那种方式存储在
    constexpr
    上下文中
原因是我在这个上下文中不是一个常量表达式

所以技巧是在常量表达式中变换
i

您正在
constepr
函数中使用
std::array
运算符[]
,因此您使用的是C++17

使用C++17,您可以使用
std::index_sequence
/
std::make_index_sequence
(从C++14开始提供)和模板折叠(从C++17开始)

因此,您可以分两步编写
gen_操作码()

根据循环长度生成
std::index_序列的第一步

constexpr auto gen_opcodes_1()
{ return gen_opcodes_2(std::make_index_sequence<20U>{}); }
constexpr自动生成操作码1()
{返回gen_操作码_2(std::make_index_sequence{})}
第二步,使用模板折叠来模拟for循环

template <std::size_t ... Is>
constexpr auto gen_opcodes_2 (std::index_sequence<Is...> const &)
 {
   std::array<Opcode, 100> ret {};

   ( (ret[30+Is] = { f<30+Is> }), ... );

   return ret;
 }
模板
constexpr自动生成操作码(std::index\u sequence const&)
{
std::数组ret{};
((ret[30+Is]={f}),…);
返回ret;
}
下面是一个完整的编译示例

#include <array>

struct CPU
 { int some_state = 0; };

template <int I>
void f (CPU & cpu)
 { cpu.some_state = I; }

struct Opcode
 { 
   using Runner = void(*)(CPU&);
   Runner run = [](CPU&) {};
 };

template <std::size_t ... Is>
constexpr auto gen_opcodes_2 (std::index_sequence<Is...> const &)
 {
   std::array<Opcode, 100> ret {};

   ( (ret[30+Is] = { f<30+Is> }), ... );

   return ret;
 }

constexpr auto gen_opcodes_1()
 { return gen_opcodes_2(std::make_index_sequence<20U>{}); }

constexpr auto opcodes = gen_opcodes_1();

int main()
 {
   CPU cpu;
   opcodes[1].run(cpu);
 }
#包括
结构CPU
{int some_state=0;};
模板
无效f(CPU和CPU)
{cpu.some_state=I;}
结构操作码
{ 
使用Runner=void(*)(CPU&);
运行程序运行=[](CPU&){};
};
模板
constexpr自动生成操作码(std::index\u sequence const&)
{
std::数组ret{};
((ret[30+Is]={f}),…);
返回ret;
}
constexpr自动生成操作码1()
{返回gen_操作码_2(std::make_index_sequence{})}
constexpr自动操作码=gen_操作码_1();
int main()
{
中央处理器;
操作码[1]。运行(cpu);
}
#include <array>

struct CPU
 { int some_state = 0; };

template <int I>
void f (CPU & cpu)
 { cpu.some_state = I; }

struct Opcode
 { 
   using Runner = void(*)(CPU&);
   Runner run = [](CPU&) {};
 };

template <std::size_t ... Is>
constexpr auto gen_opcodes_2 (std::index_sequence<Is...> const &)
 {
   std::array<Opcode, 100> ret {};

   ( (ret[30+Is] = { f<30+Is> }), ... );

   return ret;
 }

constexpr auto gen_opcodes_1()
 { return gen_opcodes_2(std::make_index_sequence<20U>{}); }

constexpr auto opcodes = gen_opcodes_1();

int main()
 {
   CPU cpu;
   opcodes[1].run(cpu);
 }