C++ 杂项工具函数收集
这里其中的许多函数都不是我自己写的,而是抄的。
天下代码一大抄嘛。
1. 给定一个整数,计算向上最接近的2的N次方
1 uint32_t next_pow2(uint32_t v) 2 { 3 --v; 4 v |= v >> 1; 5 v |= v >> 2; 6 v |= v >> 4; 7 v |= v >> 8; 8 v |= v >> 16; 9 return ++v; 10 }
2.给定一个32bit整数,计算它的二进制中出现了几次1
1 uint32_t bitcount2(uint32_t v) 2 { 3 v = v - ((v >> 1) & 0x55555555); 4 v = (v & 0x33333333) + ((v >> 2) & 0x33333333); 5 v = (v + (v >> 4)) & 0x0F0F0F0F; 6 v = v + (v >> 8); 7 v = v + (v >> 16); 8 return v & 0x0000003F; 9 }
上面代码是下面的简洁版
1 uint32_t bitcount2_2(uint32_t v) 2 { 3 v = (v & 0x55555555) + ((v >> 1) & 0x55555555); 4 v = (v & 0x33333333) + ((v >> 2) & 0x33333333); 5 v = (v & 0x0F0F0F0F) + ((v >> 4) & 0x0F0F0F0F); 6 v = (v & 0x00FF00FF) + ((v >> 8) & 0x00FF00FF); 7 v = (v & 0x0000FFFF) + ((v >> 16) & 0x0000FFFF); 8 return v; 9 }
原理是将一个32bit数分隔成16个2bit数,开始计算每个2bit中含有多少个1:
因为0x55=0b01010101,则有:
a. 0b01 & 0b01 = 1;
b. 0b01 & 0b00 = 0;
c. 0b01 & 0b10 = 0;0b01 & (0b10>>1) = 1;0 + 1 = 1;
d. 0b01 & 0b11 = 1;0b01 & (0b11>>1) = 1;1 + 1 = 2;
以下同理,只是分割粒度的不同,用分治的方法进行计算。
3.给定一个字符串,计算其hash值
1 constexpr unsigned int ELFHash(const char *str) 2 { 3 unsigned int hash = 0, 4 x = 0; 5 while (*str) 6 { 7 hash = (hash << 4) + (*str++); 8 if ((x = hash & 0xF0000000L) != 0) 9 { 10 hash ^= (x >> 24); 11 hash &= ~x; 12 } 13 } 14 return (hash & 0x7FFFFFFF); 15 }
4. 给定一变量名,获得其变量名的字符串
1 #define ___S(s) #s 2 #define __S(s) ___S(s)
5. 线程池
1 #include <mutex> 2 #include <condition_variable> 3 #include <functional> 4 #include <queue> 5 #include <thread> 6 7 namespace LC 8 { 9 10 #ifdef _WIN32 11 #include "windows.h" 12 #else 13 #include <unistd.h> 14 #endif 15 16 #ifdef _WIN32 17 SYSTEM_INFO sysInfo; 18 GetSystemInfo( &sysInfo ); 19 #define logicCoreCount sysInfo.dwNumberOfProcessors 20 #else 21 #define logicCoreCount sysconf(_SC_NPROCESSORS_ONLN) 22 #endif 23 24 25 class thread_pool 26 { 27 public: 28 explicit thread_pool(size_t thread_count) 29 { 30 init(thread_count); 31 } 32 33 thread_pool() = default; 34 thread_pool(thread_pool&&) = default; 35 36 ~thread_pool() 37 { 38 exit(); 39 } 40 41 void init(size_t th_cnt) 42 { 43 data_ = std::make_shared<data>(); 44 45 for (size_t i = 0; i < th_cnt; ++i) 46 { 47 std::thread([data = data_] { 48 std::unique_lock<std::mutex> lk(data->mtx_); 49 for (;;) 50 { 51 if (!data->tasks_.empty()) 52 { 53 //从队列中取出一个任务执行 54 auto current = std::move(data->tasks_.front()); 55 data->tasks_.pop(); 56 57 lk.unlock(); 58 current(); 59 lk.lock(); 60 } 61 else if (data->is_shutdown_) 62 break; 63 else 64 data->cond_.wait(lk); 65 } 66 }).detach(); 67 } 68 } 69 70 template <class F> 71 void execute(F&& task) 72 { 73 { 74 std::lock_guard<std::mutex> lk(data_->mtx_); 75 data_->tasks_.emplace(std::forward<F>(task)); 76 } 77 data_->cond_.notify_one(); 78 } 79 80 void exit() 81 { 82 if ((bool) data_) 83 { 84 { 85 std::lock_guard<std::mutex> lk(data_->mtx_); 86 data_->is_shutdown_ = true; 87 } 88 data_->cond_.notify_all(); 89 } 90 } 91 private: 92 struct data 93 { 94 std::mutex mtx_; 95 std::condition_variable cond_; 96 bool is_shutdown_ = false; 97 std::queue<std::function<void()>> tasks_; 98 }; 99 std::shared_ptr<data> data_; 100 }; 101 102 };
6. 计算可变参数宏的参数包中的参数个数
1 #define GET_NTH_ARG( \ 2 _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, n, ...) n 3 4 /** 5 * @brief If We want to call GET_ARG_COUNT(a, s, d), and the GET_NTH_ARG is 6 * GET_NTH_ARG(a, s, d, 16, 15, ..., 5, 4, 3(n), 2, 1), so GET_ARG_COUNT(a, s, d) return 3. 7 * 8 * @notice: It's not work in VC++. 9 */ 10 #define GET_ARG_COUNT(...) GET_NTH_ARG(__VA_ARGS__, \ 11 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
7. Excel 列名(字母)转数字(这个是我瞎鸡儿写的)
1 int Colume2Num(const std::string& str) 2 { 3 if (str.empty()) 4 return -1; 5 6 int sum = 0; 7 for (int i = 0, n = str.size() - 1; i < str.size(); ++i, --n) 8 { 9 char ch = str.at(i); 10 if (ch < 'A' || ch > 'Z') 11 return -1; 12 int a = (ch - 'A' + 1); 13 sum += a * std::pow((double)26, (double)n); 14 } 15 return sum - 1; 16 }
8. 质量很低的伪随机数
1 //生成(-1, 1)的小数,来自perlin noise 2 double random1(int x) 3 { 4 x = (x << 13) ^ x; 5 return (1.0 - ((x * (x * x * 15731 + 789221) + 1376312589) & 0x7FFFFFFF) / 1073741824.0); 6 //如果要整数,那么就把其中的两个小数干掉,返回值为int 7 // return ((x * (x * x * 15731 + 789221) + 1376312589) & 0x7FFFFFFF); 8 }
9. 质量更低的伪随机数(这个也是我瞎鸡儿写的;可以将a, b参数作为种子)
1 const int a = 49939; //只要我频率设置得够大,就没人能发现这其实是一个sin 2 const int b = 773; 3 int64_t r = (std::sin(a * x + b) + 1) * (INT64_MAX >> 1);
10. 判断类中是否存在某成员函数(这个是我瞎鸡儿写的 x 3)(垃圾玩应也就能看看没法用)(这垃圾英语水平也没法看)
1 #define __IS_HAVE_FUNC_DEF(fc) \ 2 template<typename T>\ 3 class is_has_method_##fc\ 4 {\ 5 public:\ 6 struct __size2 { char c[2]; };\ 7 \ 8 public:\ 9 template<typename C>\ 10 static __size2 __is(...);\ 11 \ 12 template<typename C>\ 13 static char __is(decltype(&C::fc));\ 14 \ 15 enum { value = (sizeof(__is<T>(0)) == sizeof(char)) };\ 16 };\ 17 \ 18 19 #define __IS_HAVE_FUNC(T, fc) is_has_method_##fc<T>::value; 20 21 __IS_HAVE_FUNC_DEF(show2) 22 __IS_HAVE_FUNC_DEF(show3) 23 24 class test 25 { 26 public: 27 int show2() { return 0; } 28 }; 29 30 int main() 31 { 32 bool isHave = __IS_HAVE_FUNC(test, show3); 33 return 0; 34 }
11. 两个时间戳是否是同一天
1 constexpr time_t HOUR_S = 60 * 60; 2 constexpr time_t DAY_S = 24 * HOUR_S; 3 constexpr int TIME_ZONE = +8; 4 bool is_same_day(time_t time_A_s, time_t time_B_s, const int64_t offset_s) 5 { 6 time_A_s = time_A_s + ((TIME_ZONE * HOUR_S) - offset_s); 7 time_B_s = time_B_s + ((TIME_ZONE * HOUR_S) - offset_s); 8 return (time_A_s / DAY_S) == (time_B_s / DAY_S); 9 }
offset_s 默认为0, 表示过了几点才算1天。例如offset_s=HOUR_S*5,表示过了5点算一天。
12. 从一个参数包中,获取第N个参数的类型(c++17)
1 template<usize_t i_, typename t_, typename ... ts_> 2 struct get_type 3 : public get_type<i_ - 1, ts_...> 4 { 5 }; 6 7 template<typename t_, typename ... ts_> 8 struct get_type<0, t_, ts_...> 9 { 10 using type = t_; 11 };