使用 C 模仿 C++ 模板的拙劣方法

如下所示,准备两个宏,一个定义类型,一个定义容器大小。

使用时只要先定义这两个宏,然后再包含容器头文件就能生成不同类型和大小的容器了。但是这种方法只允许在源文件中使用,如果在头文件中使用,定义不同类型和大小的容器时会引起宏定义冲突。

cpp 复制代码
#pragma once
#include "cb/cb_define.h"
#include <stdbool.h>
#include <stdint.h>
#include <string.h>

#ifdef __cplusplus
extern "C"
{
#endif

	///
	/// @brief 模板参数。队列元素类型。
	///
#ifndef __template_cb_circle_deque_element_type
	#define __template_cb_circle_deque_element_type int
#endif

	///
	/// @brief 模板参数。队列大小。
	///
#ifndef __template_cb_circle_deque_size
	#define __template_cb_circle_deque_size 100
#endif

	///
	/// @brief 循环队列。
	///
	typedef struct cb_circle_deque
	{
		__template_cb_circle_deque_element_type _buffer[__template_cb_circle_deque_size];
		uint32_t _begin;
		uint32_t _end;
		bool _is_full;

	} cb_circle_deque;

	///
	/// @brief 初始化。
	///
	/// @param self
	/// @return
	///
	__cb_force_inline void cb_circle_deque_initialize(cb_circle_deque *self)
	{
		self->_begin = 0;
		self->_end = 0;
		self->_is_full = false;
	}

	///
	/// @brief 队列中的元素个数。
	///
	/// @param self
	/// @return
	///
	__cb_force_inline int cb_circle_deque_count(cb_circle_deque *self)
	{
		if (self->_is_full)
		{
			return __template_cb_circle_deque_size;
		}

		if (self->_end >= self->_begin)
		{
			return self->_end - self->_begin;
		}

		return __template_cb_circle_deque_size - (self->_begin - self->_end);
	}

	///
	/// @brief 队列为空。
	///
	/// @param self
	/// @return
	///
	__cb_force_inline bool cb_circle_deque_is_empty(cb_circle_deque *self)
	{
		return self->_begin == self->_end && !self->_is_full;
	}

	///
	/// @brief 向队列末尾添加元素。
	///
	/// @param self
	/// @param value
	/// @return 添加成功返回 true, 添加失败返回 false.
	///
	__cb_force_inline bool cb_circle_deque_push_back(cb_circle_deque *self,
													 __template_cb_circle_deque_element_type *value)
	{
		if (value == NULL)
		{
			return false;
		}

		if (self->_is_full)
		{
			return false;
		}

		self->_buffer[self->_end] = *value;
		self->_end = (self->_end + 1) % __template_cb_circle_deque_size;

		if (self->_end == self->_begin)
		{
			self->_is_full = true;
		}

		return true;
	}

	///
	/// @brief 向队列头部添加元素。
	///
	/// @param self
	/// @param value
	/// @return 添加成功返回 true, 添加失败返回 false.
	///
	__cb_force_inline bool cb_circle_deque_push_front(cb_circle_deque *self,
													  __template_cb_circle_deque_element_type *value)
	{
		if (value == NULL)
		{
			return false;
		}

		if (self->_is_full)
		{
			return false;
		}

		self->_begin = (self->_begin + __template_cb_circle_deque_size - 1) % __template_cb_circle_deque_size;
		self->_buffer[self->_begin] = *value;

		if (self->_end == self->_begin)
		{
			self->_is_full = true;
		}

		return true;
	}

	///
	/// @brief 弹出队列末尾元素。
	///
	/// @param self
	/// @param out
	/// @return
	///
	__cb_force_inline bool cb_circle_deque_pop_back(cb_circle_deque *self,
													__template_cb_circle_deque_element_type *out)
	{
		if (cb_circle_deque_is_empty(self))
		{
			return false;
		}

		self->_end = (self->_end + __template_cb_circle_deque_size - 1) % __template_cb_circle_deque_size;

		if (out != NULL)
		{
			*out = self->_buffer[self->_end];
		}

		self->_is_full = false;
		return true;
	}

	///
	/// @brief 弹出队列头部元素。
	///
	/// @param self
	/// @param out
	/// @return
	///
	__cb_force_inline bool cb_circle_deque_pop_front(cb_circle_deque *self,
													 __template_cb_circle_deque_element_type *out)
	{
		if (cb_circle_deque_is_empty(self))
		{
			return false;
		}

		if (out != NULL)
		{
			*out = self->_buffer[self->_begin];
		}

		self->_begin = (self->_begin + 1) % __template_cb_circle_deque_size;
		self->_is_full = false;
		return true;
	}

	///
	/// @brief 获取队列中指定索引的元素。
	///
	/// @param self
	/// @param index
	///
	/// @return 如果指定索引处有元素,则返回该元素的指针,否则返回空指针。
	///
	__cb_force_inline __template_cb_circle_deque_element_type *cb_circle_deque_get(cb_circle_deque *self,
																				   int index)
	{
		if (index < 0 || index >= cb_circle_deque_count(self))
		{
			return NULL;
		}

		uint32_t pos = (self->_begin + index) % __template_cb_circle_deque_size;
		return &self->_buffer[pos];
	}

	///
	/// @brief 清空队列。
	///
	/// @param self
	/// @return
	///
	__cb_force_inline void cb_circle_deque_clear(cb_circle_deque *self)
	{
		self->_begin = 0;
		self->_end = 0;
		self->_is_full = false;
	}

#ifdef __cplusplus
}
#endif
相关推荐
小狗爱吃黄桃罐头23 分钟前
《C++ Primer Plus》模板类 Template 课本实验
c++
无限进步_30 分钟前
C语言数组元素删除算法详解:从基础实现到性能优化
c语言·开发语言·windows·git·算法·github·visual studio
月殇_木言38 分钟前
Python期末复习
开发语言·python
松涛和鸣38 分钟前
16、C 语言高级指针与结构体
linux·c语言·开发语言·数据结构·git·算法
毕设源码余学姐1 小时前
计算机毕设 java 中医药药材分类采购网站 SSM 框架药材交易平台 Java 开发的分类采购与订单管理系统
java·开发语言·课程设计
降临-max2 小时前
JavaSE---网络编程
java·开发语言·网络·笔记·学习
湖边看客2 小时前
antd x6 + vue3
开发语言·javascript·vue.js
口袋物联2 小时前
设计模式之适配器模式在 C 语言中的应用(含 Linux 内核实例)
c语言·设计模式·适配器模式
小离a_a2 小时前
flex垂直布局,容器间距相等
开发语言·javascript·ecmascript
傻啦嘿哟3 小时前
物流爬虫实战:某丰快递信息实时追踪技术全解析
java·开发语言·数据库