2017-01-11 10 views
0

概念の証明の一部として、私はGLSLスクリプトを構築するために使用できるコードを作成しようとしています。私がやった最初のことの1つは、GLSL型への参照を作成し、GLSLでそれを表す文字列リテラル(GLSLデータ型の型)であるenumに基づいてクエリを実行できるシステムを作成することですコード。このコードで重複を取り除くにはどうすればよいですか?

#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カーネルコードを書くための同様のコードを書くことにします(これは同様のセマンティクスに依存します)。私は各タイプの1つの宣言が必要なので、コードダウン?

また、私のマクロの使用を減らすか、または排除する助言があれば、喜んでいただけると思います。

答えて

1

私は、これはあなたのケースに合うかどうかわからないが、私のようなものを提案することができます:あなたは、あなたが好きなようにマクロを定義し、必要な場所に含めることができ

// 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 

を:

// 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)"; 
} 

また、constexprマップを使用することもできます。

+0

私はこれを私のニーズに適応させる必要がありますが、テストしてそれが機能するかどうかを確認します。 – Xirema

関連する問題