通过元编程在编译时对函数数组进行初始化 [英] Function array initialization at compile time with metaprograming
问题描述
在视频游戏中,通常以逐步方式加载资源,因此在单个线程内,加载栏可以在每个加载步骤中更新.例如:
In video-games is common that resources are loaded in a step fashion way, so within a single thread a loading bar can update at each loading step. By example:
1->加载纹理A
1 -> Load texture A
2->将加载栏更新为2%
2 -> Update Loading Bar to 2%
3->加载纹理B
4->将加载栏更新为4%
4 -> Update Loading Bar to 4%
5 ...
这可以通过多种方式完成.其中之一是为每个加载步骤定义一个函数.
This can be done in many ways. One of these is define a function for each loading step.
void LoadTextureA()
{
//Loading routine
...
}
这具有可读性的优势,不需要太多的嵌套代码,甚至在某些情况下甚至有可能在两个游戏状态之间共享加载例程.
This has the advantage of readability, not need too much nested code and even possible in some cases to share loading routines between two game states.
现在我在想的是用模板来概括这种按功能运行"模型.可以说.
Now what I was thinking was to generalize this "function-for-step" model with templates. Lets say.
template <int S>
struct Foo{
void LoadingStep()
{
}
};
template <>
struct Foo<0>
{
void LoadingStep()
{
//First loading step
...
}
};
如果我错了,请纠正我.但是似乎可以使用元编程在0 ..到N个步骤进行编译时迭代,并将此专用函数分配给函数指针的数组或向量. 在编译时已知N个步骤及其相应的功能. 函数指针向量将像这样迭代:
Please correct me if I'm wrong. But it appears possible that I can compile-time iterate through 0 .. to N steps using metaprogramming and assign this specialized functions to an array or vector of function pointers. N steps are known at compile time along with it respective functions. Function pointer vector would be iterated like this:
template <int Steps>
class Loader {
public:
bool Load()
{
functionArray[m_step]();
if (++m_step == Steps)
return false; //End loading
else
return true;
}
private:
int m_step;
}
这可能吗?我知道这是更简单的方法.但是除了项目要求外,这是一个有趣的编程挑战
推荐答案
我是基于类似问题的Kal答案实现的 在C ++ 11中创建N元素constexpr数组
I achieved it based on Kal answer of a similar problem Create N-element constexpr array in C++11
template <int S>
struct Foo{
static void LoadingStep()
{
}
};
template <>
struct Foo<0>
{
static void LoadingStep()
{
//First loading step
}
};
template<template<int S> class T,int N, int... Rest>
struct Array_impl {
static constexpr auto& value = Array_impl<T,N - 1, N, Rest...>::value;
};
template<template<int S> class T,int... Rest>
struct Array_impl<T,0, Rest...> {
static constexpr std::array<void*,sizeof...(Rest)+1> value = {reinterpret_cast<void*>(T<0>::LoadingStep),reinterpret_cast<void*>(T<Rest>::LoadingStep)...};
};
template<template<int S> class T,int... Rest>
constexpr std::array<void*,sizeof...(Rest)+1> Array_impl<T,0, Rest...>::value;
template<template<int S> class T,int N>
struct F_Array {
static_assert(N >= 0, "N must be at least 0");
static constexpr auto& value = Array_impl<T,N>::value;
F_Array() = delete;
F_Array(const F_Array&) = delete;
F_Array(F_Array&&) = delete;
};
使用示例:
int main()
{
auto& value = F_Array< Foo ,4>::value;
std::cout << value[0] << std::endl;
}
这将产生void *指向模板函数的指针数组:
This yields of void* array of pointers to template functions:
Foo<0>::LoadinStep()
Foo<1>::LoadinStep()
Foo<2>::LoadinStep()
Foo<3>::LoadinStep()
Foo<4>::LoadinStep()
由于Foo< 1..3>不是专门的,因此它们将属于Default LoadingStep功能
Since Foo<1..3> are not specialized they will fall to Default LoadingStep function
这篇关于通过元编程在编译时对函数数组进行初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!