// jave.lin #include #define __TO_STR(f1,f2) "__"#f1"_"#f2"__" // 字符串拼接 #define __CONNECT__FLAG(f1, f2) __##f1##_##f2##__ // 宏参数拼接成符号 #define __CALL(f1, f2) __CONNECT__FLAG(f1, f2) // 宏嵌套 #define __CONNTECT__ARGS(...) (__VA_ARGS__) // 宏变长参数 #define __CALL2(f1,f2,...) __CALL(f1,f2)__CONNTECT__ARGS(__VA_ARGS__) // 嵌套+变长参数 void __a_b__() { std::cout << __TO_STR(a,b) << "\n"; } void __c_d__() { std::cout << __TO_STR(c,d) << "\n"; } void __e_f__(int a, int b) { std::cout << __TO_STR(e,f) << " : " << a << " + " << b << " = " << (a + b) << "\n"; } void __g_h__(const char* a, const char* b, const char* c) { std::cout << __TO_STR(g,h) << " : a : " << a << ", b : " << b << ", c : " << c << "\n"; } int main() { std::cout << "=== Test1 ===\n"; __CALL(a,b)(); __CALL(c,d)(); std::cout << "\n=== Test2 ===\n"; __CALL2(a,b); __CALL2(c,d); __CALL2(e,f,2,6); __CALL2(g,h,"a string","b string","c string"); return 0; } /* 输出:
=== Test1 ===
__a_b__
__c_d__
=== Test2 ===
__a_b__
__c_d__
__e_f__ : 2 + 6 = 8
__g_h__ : a : a string, b : b string, c : c string
*/
我们可以用-E编译参数,查看预编译后的内容:g++ -E .\a.cpp > a.pre,输出到 a.pre 文件。
查看该文件内容:
...[这里是一堆 #include<iostream> 的内容]... # 3 ".\\a.cpp" 2 # 12 ".\\a.cpp" # 12 ".\\a.cpp" void __a_b__() { std::cout << "__""a""_""b""__" << "\n"; } void __c_d__() { std::cout << "__""c""_""d""__" << "\n"; } void __e_f__(int a, int b) { std::cout << "__""e""_""f""__" << " : " << a << " + " << b << " = " << (a + b) << "\n"; } void __g_h__(const char* a, const char* b, const char* c) { std::cout << "__""g""_""h""__" << " : a : " << a << ", b : " << b << ", c : " << c << "\n"; } int main() { std::cout << "=== Test1 ===\n"; __a_b__(); __c_d__(); std::cout << "\n=== Test2 ===\n"; __a_b__(); __c_d__(); __e_f__(2,6); __g_h__("a string","b string","c string"); return 0; }
这里在添加一个我之前应该到 LearnGL 系列中的使用宏来定义函数的方法,方便处理重复冗余的代码编写:
// jave.lin - 测试,使用宏来更便利的定义函数 #include #include #include // #define __TO_STR(f1,f2) "__"#f1"_"#f2"__" // 字符串拼接 // #define __CONNECT__FLAG(f1, f2) __##f1##_##f2##__ // 宏参数拼接成符号 // #define __CALL(f1, f2) __CONNECT__FLAG(f1, f2) // 宏嵌套 // #define __CONNTECT__ARGS(...) (__VA_ARGS__) // 宏变长参数 // #define __CALL2(f1,f2,...) __CALL(f1,f2)__CONNTECT__ARGS(__VA_ARGS__) // 嵌套+变长参数 #define __SET_GLOBAL(unifom_name, funs_name, ...)\
{\
std::vector::iterator b = ShaderProgram::vec.begin();\
std::vector::iterator e = ShaderProgram::vec.end();\
ShaderProgram* s = NULL;\
for (; b != e; ) {\
s = *b;\
if (s->isDestroy()) {\
b = ShaderProgram::vec.erase(b);\
continue;\
}\
else {\
b++;\
}\
if (!s->link()) {\
std::cout << "shader : " << s->name << " un link, but in the shader pool list.";\
continue;\
}\
GLint loc = s->getUniformLoc(unifom_name);\
s->funs_name(loc, __VA_ARGS__);\
}\
} #define DEF_GLOBAL_SET_UNIFORM_VEC(one, vec, type, flag)\
static void setGlobal##one(const char* name, const type value)\
__SET_GLOBAL(name, set##one, value) typedef int GLint; typedef float GLfloat; class ShaderProgram { public: // static DEF_GLOBAL_SET_UNIFORM_VEC(Float, Array, GLfloat, f) DEF_GLOBAL_SET_UNIFORM_VEC(Int, Array, GLint, i) static std::vector<ShaderProgram*> vec; // local member ShaderProgram(); ~ShaderProgram(); GLint getUniformLoc(const char* name); void setFloat(GLint loc, GLfloat value); void setInt(GLint loc, GLint value); bool link() const; bool isDestroy() const; char* name = NULL; }; // static std::vector<ShaderProgram*> ShaderProgram::vec; // local member ShaderProgram::ShaderProgram() { vec.push_back(this); } ShaderProgram::~ShaderProgram() { std::vector<ShaderProgram*>::iterator ret = find(vec.begin(), vec.end(), this); if (ret != vec.end()) { vec.erase(ret); } } GLint ShaderProgram::getUniformLoc(const char* name) { return 0; } void ShaderProgram::setFloat(GLint loc, GLfloat value) { } bool ShaderProgram::link() const { return false; } bool ShaderProgram::isDestroy() const { return false; } int main() { ShaderProgram s; return 0; } /* 输出:
*/
这样我们只要先定义好 setXXX 的成员函数,就可以使用DEF_GLOBAL_SET_UNIFORM_VEC宏来定义 setGlobalXXX 的静态函数了
