定义一个结构并在一次传递中创建相关数据项的列表?

时间:2015-01-16 11:42:01

标签: c++ macros template-meta-programming

我希望实现一个系统,我可以使用一组宏(或模板)在一次传递中创建结构和一些数据。它将被用于这样的东西(语法不是固定的,任何有效的东西都可以):

def_vert(MyVertex)
{
    element(float, 3, Position,     POSITION, 0);
    element(float, 3, Normal,       NORMAL, 0);
    element(float, 2, UVa,          TEXCOORD, 0);
    element(float, 2, UVb           TEXCOORD, 1);
    element(float, 4, DiffuseColor, COLOR, 0);
}
end_def()

并输出:

struct MyVertex
{
    float3 Position;
    float3 Normal;
    float2 UVa;
    float2 UVb;
    float4 DiffuseColor;
};

以及

field_definition MyVertex_field_defs[] =
{
    { "POSITION", 0, float_type, 3 },
    { "NORMAL", 0, float_type, 3 },
    { "TEXCOORD", 0, float_type, 2 },
    { "TEXCOORD", 1, float_type, 2 },
    { "COLOR", 0, float_type, 4 }
};

我无法使用宏或TMP看到这样做的方法(创建2个独立的输出块) - 是否有人知道它是否可能?我不能直接使用boost,但知道这是否能提供解决方案会很有用。

一个严峻的选择是使用这样的包含文件:

MyVertex.h 包含定义
def_makestruct.h 包含用于创建结构的宏 def_makefields.h 包含用于创建字段的宏

然后:

#include "def_makestruct.h"
#include "MyVertex.h"
#include "def_makefields.h"
#include "MyVertex.h"

所以我至少只需要在一个地方编辑定义,但它必须在它自己的文件中。还有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

您要实现的目标称为X Macro

如果您不希望在每个扩展站点包含任何文件或提供element / def_vert / end_vert定义,则可以将它们作为额外参数传递给MyVertexDef宏。

#define MyVertexDef(def_vert, element, end_def) \
def_vert(MyVertex) \
    element(float, 3, Position, POSITION, 0) \
    element(float, 3, Normal, NORMAL, 0) \
    element(float, 2, UVa, TEXCOORD, 0) \
    element(float, 2, UVb,           TEXCOORD, 1) \
    element(float, 4, DiffuseColor, COLOR, 0) \
end_def()

#define struct_def_vert(name) struct name {
#define struct_end_def() };
#define struct_element(type, size, name, meaning, index) type name; 

#define array_def_vert(name) field_definition name##_field_defs[] = {
#define array_end_def() };
#define array_element(type, size, name, meaning, index) {#name, index, type##_type, size},

#define GenerateStruct(T) T(struct_def_vert, struct_element, struct_end_def)
#define GenerateArray(T) T(array_def_vert, array_element, array_end_def)
...
//Where you want your struct MyVertex
GenerateStruct(MyVertexDef)
...
//Where you want MyVertex_field_defs
GenerateArray(MyVertexDef)

答案 1 :(得分:0)

我遇到了类似的问题,我使用了后续的tecnique,以避免写两次相同的字符串。

定义将在文件上使用的宏:

只在名为data.cpp

的文件中写入所需数据一次
mcr(NORMAL,3,Normal)
mcr(TEXCOORD,2,UVa)
mcr(TEXCOORD,2,UVb)
mcr(COLOR,4,DiffuseColor)

在另一个文件中写

#define mcr(a,b,c,etc) define_as_needed
struct MyVertex
{
#include "data.cpp"
}
#undef mcr

#define mcr(a,b,c,etc) define_as_needed

重新定义宏

#define mcr(a,b,c,etc) define_as_needed

field_definition MyVertex_field_defs[] =
{
#include "data.cpp"
};

#undef mcr

在我的情况下,我根据每次更改宏的定义需要进行4次重新定义3次。

根据您的需求调整代码。 特别是对于常量的定义以及结构中相关字符串和数据的定义,它非常方便。