首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何消除代码中的重复?

如何消除代码中的重复?
EN

Stack Overflow用户
提问于 2017-01-11 21:44:54
回答 1查看 54关注 0票数 0

作为概念证明的一部分,我试图构建我可以用来构建GLSL脚本的代码。我所做的第一件事是创建对GLSL类型的引用,并创建一个可以在其中查询的系统,该系统基于一个枚举(这是GLSL数据类型的类型)--在GLSL代码中表示它的字符串-文字。看上去是这样的:

代码语言:javascript
复制
#define VEC_EXPAND(name) g ## name ## 2, g ## name ## 3, g ## name ## 4
#define MAT_EXPAND(name) VEC_EXPAND(name), VEC_EXPAND(name ## 2x), VEC_EXPAND(name ## 3x), VEC_EXPAND(name ## 4x)

enum class gtype : uint32_t {
    gvoid,
    gbool, gint, guint, gfloat, gdouble,
    VEC_EXPAND(bvec), VEC_EXPAND(ivec), VEC_EXPAND(uvec), VEC_EXPAND(vec), VEC_EXPAND(dvec),
    MAT_EXPAND(mat), MAT_EXPAND(dmat),
    gsampler2d
};

#undef VEC_EXPAND
#undef MAT_EXPAND

#define GLSL_EXPAND(name) #name
#define VEC_EXPAND(name) GLSL_EXPAND(name ## 2), GLSL_EXPAND(name ## 3), GLSL_EXPAND(name ## 4)
#define MAT_EXPAND(name) VEC_EXPAND(name), VEC_EXPAND(name ## 2x), VEC_EXPAND(name ## 3x), VEC_EXPAND(name ## 4x)

template<class T, class... Tail, class Elem = typename std::decay<T>::type>
constexpr std::array<Elem, 1 + sizeof...(Tail)> make_array(T&& head, Tail&&... values)
{
    return { std::forward<T>(head), std::forward<Tail>(values)... };
}


constexpr auto glsl_string_array = make_array(
    "void", "bool", "int", "uint", "float", "double",
    VEC_EXPAND(bvec), VEC_EXPAND(ivec), VEC_EXPAND(uvec), VEC_EXPAND(vec), VEC_EXPAND(dvec),
    MAT_EXPAND(mat), MAT_EXPAND(dmat),
    "sampler2d"
);
constexpr const char * to_string_literal(gtype type) {
    return glsl_string_array[uint32_t(type)];
}

std::string to_string(gtype type) {
    return to_string_literal(type);
}

#undef GLSL_EXPAND
#undef VEC_EXPAND
#undef MAT_EXPAND

到目前为止,我对代码的功能没有任何问题,但是代码的复制(我将类型定义为枚举,然后将它们再次写为字符串文本)对我来说无疑是个麻烦。我还需要添加更多的类型(这不是唯一的GLSL类型!)我想编写类似的代码来编写OpenCL内核代码(这将取决于类似的语义),那么我如何将该代码降下来,使我只需要每种类型的一个声明?

此外,任何能减少甚至消除我对宏的使用的建议都将不胜感激。

EN

回答 1

Stack Overflow用户

发布于 2017-01-11 23:06:44

我不知道这是否适合你的情况,但我可以建议如下:

代码语言:javascript
复制
// things.inc
#ifndef GTYPE_VOID
#define GTYPE_VOID GTYPE_DECL(gvoid)
#endif
GTYPE_VOID

#undef GTYPE_VOID
#ifndef GTYPE_INT
#define GTYPE_INT GTYPE_DECL(gint)
#endif
GTYPE_INT
#undef GTYPE_INT

#ifndef GTYPE_FLOAT
#define GTYPE_FLOAT GTYPE_DECL(gfloat)
#endif
GTYPE_FLOAT
#undef GTYPE_FLOAT

然后,您可以按自己喜欢的方式定义宏,并将其包含在需要的地方:

代码语言:javascript
复制
// things.cpp
enum class gtypes {
#define GTYPE_DECL(Thing) Thing,
#include "things.inc"
#undef GTYPE_DECL
};
const char *as_string(gtype t) {
  switch (t) {
  #define GTYPE_DECL(Thing) case gtype::Thing: return #Thing;
  #include "things.inc"
  #undef GTYPE_DECL
  }
  // or unreachable
  return "(unknown)";
}

此外,你也可以尝试使用一张警察地图。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41601243

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档