C++ 宏字符串拼接、宏参数拼接成符号、宏嵌套、宏变长参数

// 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 的静态函数了

在这里插入图片描述

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值