介绍一下自己写的几个简单易用的工具包。

  • 用到了部分 C++14 的特性(ISO C++14标准)。
  • 吐槽一下:C++ 某些老东西为了兼容 C 弄得真是特别不好用。
  • 工具源码:这里
  • 有空会继续更新。

Utils

m_cal_time.h

用来计算函数执行时间的工具,使用方法见下面的示例:

auto f1 = [](int i, int j, int k) -> std::vector<int>
{
	std::vector<int> r(i * j * k);
	size_t cnt = 0;
	for (int x = 1; x <= i; ++x)
	{
		for (int y = 1; y <= j; ++y)
		{
			for (int z = 1; z <= k; ++z)
			{
				r[cnt++] = x * y * z;
			}
		}
	}
	return r;
};

auto f2 = [](int i, int j, int k) -> void
{
	for (int x = 1; x <= i; ++x)
	{
		for (int y = 1; y <= j; ++y)
		{
			for (int z = 1; z <= k; ++z)
			{
			}
		}
	}
};

auto r1 = morisa::m_cal_time_with_return(f1, 100, 100, 100);
std::cout << "time: " << r1.time_ms << "ms\n";
std::cout << "r last: " << r1.data[r1.data.size() - 1] << "\n";

auto r2 = morisa::m_cal_time(f2, 100, 100, 100);
std::cout << "time: " << r2.time_ms << "ms\n";

执行结果:

time: 5ms r last: 1000000 time: 2ms

有返回值的函数可以用 m_cal_timem_cal_time_with_return,无返回值的函数只能用 m_cal_time

m_log.h

用来输出日志信息的工具,使用方法见下面的示例:

auto f = [](int x, int y) -> int
{
	if (y == 0)
	{
		throw std::runtime_error("Zero can't be divisor.");
	}
	return x / y;
};
try
{
	f(1, 0);
}
catch (std::runtime_error& e)
{
	morisa::m_log(e.what());
}

morisa::m_log("morisa66\n", "game over");

日志记录:

Sat Mar 20 11:23:34 2021 Zero can't be divisor.

Sat Mar 20 11:23:34 2021 morisa66 game over

  • 日志路径可以修改宏定义 LOG_PATH
  • 确保调用的是 m_log 而不是 _m_log
  • 支持线程锁。

m_shared_ptr.h

实现的简易共享指针,支持多线程安全,使用方法见下面的示例:

class Base
{
public:
	virtual ~Base() {}

};

class A : public Base
{
public:
	~A() { morisa::m_log("~A"); }
};

int main()
{
	using morisa::m_shared_ptr;
	using morisa::m_dynamic_cast;
	using morisa::m_static_cast;
	using morisa::m_log;

	m_shared_ptr<A> p1(new A());
	m_log("p1: ", p1.get_counter());			// p1: 1
	m_shared_ptr<Base> p2;
	m_log("p2: ", p2.get_counter());			// p2: 0
	p2 = p1;
	m_log("p2: ", p2.get_counter());			// p2: 2
	m_shared_ptr<A> p3 = m_dynamic_cast<A>(p2);			
	m_log("p3: ", p3.get_counter());			// p3: 3
	m_shared_ptr<Base> p4 = m_static_cast<Base>(p3);	
	m_log("p4: ", p4.get_counter());			// p4: 4
	m_log("p1: ", p1.get_counter());			// p1: 4
	p1.release();
	m_log("p1: ", p1.get_counter());			// p1: 0
	m_log("p4: ", p4.get_counter());			// p4: 3
	return 0;									// ~A
}

m_fun.h

复合函数 m_composite_fun

auto f1 = [](auto&& v)
{
	return v + v;
};

auto f2 = [](auto&& v)
{
	return v * v;
};

std::cout << morisa::m_composite_fun(f1, f2)(10); // f1(f2(10)) = 200 

在编译期判断某个类是否有某个成员函数 m_has_xxx

struct Obj
{
	void reserve(size_t i) {};
	void emplace_back(Obj obj) {};
};

int main()
{
	using type_v = std::vector<Obj>;
	using std::cout;
																	 
	cout << morisa::m_has_reserve<type_v>::value << "\n";			 //	true
	cout << morisa::m_has_reserve<Obj>::value << "\n";				 //	true
	cout << morisa::m_has_resize<type_v>::value << "\n";			 //	true
	cout << morisa::m_has_resize<Obj>::value << "\n";				 //	false
	cout << morisa::m_has_emplace_back<type_v, Obj>::value << "\n";	 //	true
	cout << morisa::m_has_emplace_back<Obj, Obj>::value << "\n";	 //	true

	return 0;									
}

m_jthread.h

简单封装了一下 thread(C++ 20会出来 jthread)。

  • 自动 join
  • 支持移动构造和赋值。

使用方法见下面的示例:

std::mutex mtx01;
std::condition_variable cv;
bool ready = false;

void fun(int i)
{
	std::unique_lock<std::mutex> lck(mtx01);
	while (!ready)
	{
		cv.wait(lck);
	}
	morisa::m_log("thread", i);
}

void start() 
{
	std::unique_lock<std::mutex> lck(mtx01);
	ready = true;
	cv.notify_one();  // cv.notify_one()
}

int main()
{
	using morisa::m_jthread;
	const int N = 10;
	m_jthread threads[N];
	for (int i = 0; i < N; ++i)
	{
		threads[i] = m_jthread(fun, i);
	}
	start();
	return 0;
}

日志里面会打印出 thread 0 ~ 9