// 模板参数类型区分
template <class T>
static std::string cppdemangle() {
std::string s{cppdemangle(typeid(std::remove_cv_t<std::remove_reference_t<T>>))};
if (std::is_const_v<std::remove_reference_t<T>>)
s += " const";
if (std::is_volatile_v<std::remove_reference_t<T>>)
s += " volatile";
if (std::is_lvalue_reference_v<T>)
s += " &";
if (std::is_rvalue_reference_v<T>)
s += " &&";
return s;
}
// 显示转换枚举值
template <class T, std::enable_if_t<std::is_enum_v<T>, int> = 0>
constexpr std::underlying_type_t<T> to_underlying(T t) noexcept {
return static_cast<std::underlying_type_t<T>>(t);
}
template <class T, std::enable_if_t<!std::is_enum_v<T>, int> = 0>
constexpr T to_underlying(T t) noexcept {
return t;
}
//文件操作
static std::string file_get_content(std::string const &path) {
std::ifstream fin(path);
std::string content;
std::istreambuf_iterator<char> iit(fin), eiit;
std::back_insert_iterator<std::string> sit(content);
std::copy(iit, eiit, sit);
return content;
}
static void file_put_content(std::string const &path, std::string const &content) {
std::ofstream fout(path);
fout << content;
}
static bool file_exists(std::string const &path) {
std::ifstream fin(path);
return (bool)fin;
}
// win min max冲突
#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif
/* FUN FACT: DID YOU KNOW THAT MICROSOFT BUYS GITHUB? */
#if __has_include(<windows.h>)
#include <windows.h>
#elif __has_include(<math.h>)
#include <math.h>
#endif
/* FUN FACT: DID YOU KNOW THAT MICROSOFT INVENTS VSCODE? */
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
#ifdef near
#undef near
#endif
#ifdef far
#undef far
#endif
#endif
// 耗时
#define TICK(x) auto bench_##x = std::chrono::steady_clock::now();
#define TOCK(x) std::printf("%s: %lfs\n", #x, std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::steady_clock::now() - bench_##x).count());
// 随机字符串生成
inline std::string randomStringGenerator(const int len)
{
std::string res;
static const char alphanum[] = "0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < len; ++i)
res += alphanum[((size_t)std::rand() % (sizeof(alphanum) - 1))];
return res;
}
// C++20之三目运算
template<typename T>
void compare(T x, T y)
{
auto ret = x <=> y;
std::cout << "name: " << typeid(ret).name() << std::endl;
if (ret < 0)
std::cout << "x < y:" << x << "," << y << std::endl;
else if (ret == 0)
std::cout << "x == y:" << x << "," << y << std::endl;
else
std::cout << "x > y:" << x << "," << y << std::endl;
}
// C++20之字符与数值转换
#include <charconv>
// std::to_chars: converts an integer or floating-point value to a character sequence
std::array<char, 10> buffer;
// 注意:std::errc没有到bool的隐式转换,所以你不能像下面这样检查: if (res.ec) {} or if (!res.ec) {}
if (auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), val_int); ec == std::errc()) {
std::cout << "str:" << std::string_view(buffer.data(), ptr - buffer.data()) << "\n"; // str:88
*ptr = '\0'; // 保证结尾有一个空字符
std::cout << "buffer:" << buffer.data() << "\n"; // buffer:88
} else {
std::cerr << "fail to call to_char:" << std::make_error_code(ec).message() << "\n";
return -1;
}
auto str2 = "456.789";
float val2{ 0.f };
auto [ptr2, ec2] = std::from_chars(str2.data(), str2.data() + str2.size(), val2);
if (ec2 == std::errc())
std::cout << "val2:" << val2 << "\n"; // val2:456.789
else if (ec2 == std::errc::invalid_argument)
std::cerr << "Error: this is not a number: " << str2 << "\n";
else if (ec2 == std::errc::result_out_of_range)
std::cerr << "Error: this number is larger than an float: " << str2 << "\n";
else
std::cerr << "fail to call from_chars:" << std::make_error_code(ec2).message() << "\n";
// C++17之并行策略
#include <algorithm>
#include <iostream>
#include <vector>
#include <execution>
std::vector<int> v = { 5, 2, 3, 1, 4 };
std::vector<int> v2(5);
std::sort(std::execution::seq, v.begin(), v.end()); // 向量
std::for_each(std::execution::unseq, v.begin(), v.end(), [](int x) { std::cout << x << " "; }); // 向量化单线程
std::transform(std::execution::par, v1.begin(), v1.end(), v2.begin(), [](int x) { return x * x; }); // 多线程
std::for_each(std::execution::par_unseq, v.begin(), v.end(), [](int x) { std::cout << x << " "; }); // 硬软件或SMID
https://www.geeksforgeeks.org/execution-policy-of-stl-algorithms-in-modern-cpp/
// C++头文件定义全局变量
class InlineVariable {
public:
inline static int var{ 10 }; // 不带inline,则只能在类外初始化;即使在类外初始化,如果被多个cpp文件包含也会error;带inline后,即使被多个cpp文件包含也OK
inline static std::string name{ "Messy_Test" }; // 整个程序中只有一个
inline static thread_local int count{ 1 }; // 每个线程有一个
std::string city{ "BeiJing" }; // 每个实例有一个
};
inline InlineVariable inline_variable; // 不带inline,则会报重复定义;带inline后,即使被多个cpp文件包含也OK
// 获取实际对象地址
std::addressof(c)
C++ 现代教程二-CSDN博客