Code:
#include <iostream>
#include <vector>
#include <array>
#include <initializer_list>
#include <assert.h>
#include <string>
struct XNode
{
std::vector<std::string> def, in, out;
std::vector<int> jumps;
};
template<typename T>
struct list
{
list(std::initializer_list<T> list): m_list(list) {}
std::initializer_list<T> m_list;
};
typedef list<std::initializer_list<std::string>> lists;
typedef list<int> listn;
XNode AddNode(std::initializer_list<std::string> Defs, std::initializer_list<std::string> In,
std::initializer_list<std::string> Out, std::initializer_list<int> Jumps)
{
XNode tmp;
for (auto& elem : Defs)
tmp.def.push_back(elem);
for (auto& elem : In)
tmp.in.push_back(elem);
for (auto& elem : Out)
tmp.out.push_back(elem);
for (auto& elem : Jumps)
tmp.jumps.push_back(elem);
return tmp;
}
template<int N>
void FillNodesRec(std::array<XNode, N>&, int) {}
template<int N, typename... NodeArgs_t>
void FillNodesRec(std::array<XNode, N>& Nodes, int index, const lists& Data1, const listn& Data2, NodeArgs_t... NodeArgs)
{
assert(Data1.m_list.size() == 3); // There shall be exactly 3 arguments: defs, ins and outs
Nodes[index] = AddNode(Data1.m_list.begin()[0], Data1.m_list.begin()[1], Data1.m_list.begin()[2], Data2.m_list);
FillNodesRec(Nodes, index + 1, NodeArgs...);
}
template<int N, typename... NodeArgs_t>
void FillNodes(std::array<XNode, N>& Nodes, NodeArgs_t... NodeArgs)
{
static_assert(sizeof...(NodeArgs_t) == N*2, "Number of nodes passed must equal number of nodes in the array.");
FillNodesRec(Nodes, 0, NodeArgs...);
}
int main()
{
std::array<XNode, 14> Nodes;
// Jumps back edges are 1-indexed.
FillNodes(Nodes,
lists({ { "c" }, { "r3" }, {} }), listn({ }),
lists({ { "p" }, { "r1" }, {} }), listn({ 1 }),
lists({ {}, { "p" }, {} }), listn({ 2 }),
lists({ { "r1" }, { "p" }, {} }), listn({ 3 }),
lists({ { "r1", "r2" }, { "r1" }, {} }), listn({ 4 }),
lists({ { "s" }, { "r1" }, {} }), listn({ 5 }),
lists({ { "r1" }, { "p" }, {} }), listn({ 6 }),
lists({ { "r1", "r2" }, { "r1" }, {} }), listn({ 7 }),
lists({ { "t" }, { "r1" }, {} }), listn({ 8 }),
lists({ { "u" }, { "s", "t" }, {} }), listn({ 9 }),
lists({ { "u" }, {}, {} }), listn({ 3 }),
lists({ { "r1" }, { "u" }, {} }), listn({ 11, 10 }),
lists({ { "r3" }, { "c" }, {} }), listn({ 12 }),
lists({ {}, { "r1", "r3" }, {} }), listn({ 13 })
);
For some reason, taking the initializer list in list by (const) reference makes the compiler crash.