// jave.lin
#include<iostream>
#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<iostream>
#include<vector>
#include<algorithm>
// #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<ShaderProgram*>::iterator b = ShaderProgram::vec.begin();\
std::vector<ShaderProgram*>::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 的静态函数了