c++17功能示例全览

/*
 * @Author: your name
 * @Date: 2022-01-02 10:32:09
 * @LastEditTime: 2022-01-02 11:44:31
 * @LastEditors: Please set LastEditors
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: \qt_project\c++17\main.cpp
 */
#include <iostream>
#include <any>
#include <variant>
#include <string_view>
#include <map>
#include <filesystem>
#include <set>
#include <algorithm>
#include <numeric>
#include <execution>
#include <execution>
#include <functional>
 
//if constexpr
template <int N, int... Ns>
auto sum()
{
	if constexpr (0 == sizeof...(Ns)) //编译期判断参数为空返回N
		return N;
	else //需要else,不能去掉
		return N + sum<Ns...>(); //不为空进行递归
}
//折叠表达式
template<typename ...Ns> //任意参数个数,...表达参数包 return后面的()表示自己调用自己递归
auto sum(Ns... ns) {
	//一元折叠表达式 右折叠
	return (ns + ...); //ns示每个参数,...表示参数解包,ns在+号左边表示右折叠 (((1 + 2) + 3) + 4) + 5
    //一元折叠表达式 左折叠
	return (... + ns); //ns示每个参数,...表示参数解包,ns在+号左边表示左折叠 1 + (2 + (3 + (4 + 5)))
	//二元折叠表达式 右折叠
	return (0 + ... + ns);; //默认有一个参数0
	//二元折叠表达式 右左折叠
	return (ns + ... + 0); //默认有一个参数0
}
int main()
{
	//string_view 提供字条串视图,减少拷贝
	std::cout << "-----------------------------" << std::endl;
	std::string str("   hello, world ");
	std::string_view viewStr(str);
	std::cout << viewStr.substr(viewStr.find_first_not_of(' ')) << std::endl;
	std::cout << "-----------------------------" << std::endl;
	//提供文件系统管理
#ifdef WIN32
    
	std::cout << std::filesystem::current_path() << std::endl;
	std::filesystem::create_directories("sandbox/a");
	for (auto& p : std::filesystem::recursive_directory_iterator(std::filesystem::current_path().string() + "/../b"))
	{
		std::cout << p.is_directory() << " " << p.path() << std::endl;
	}
    //目标目录或文件存在、源目录/文件不存在,会abort
    std::filesystem::copy(std::filesystem::current_path().string() + "/../b", std::filesystem::current_path().string() + "/b"); //目录拷贝
    bool ok = std::filesystem::copy_file(std::filesystem::current_path().string() + "/../bb", std::filesystem::current_path().string() + "/xx"); //文件拷贝
    ok = std::filesystem::remove(std::filesystem::current_path().string() + "/../dd");
#else
    //g++ 9.3以下
    #include <experimental/filesystem>

    std::cout << std::experimental::filesystem::current_path() << std::endl;
	std::experimental::filesystem::create_directories("sandbox/a");
	for (auto& p : std::experimental::filesystem::recursive_directory_iterator(std::filesystem::current_path().string() + "/../b"))
	{
		std::cout << p.status().type() << " " << p.path() << std::endl;
	}
    std::filesystem::experimental::copy(std::experimental::filesystem::current_path().string() + "/../b", std::experimental::filesystem::current_path().string() + "/b"); //目录拷贝
    std::filesystem::experimental::copy_file(std::experimental::filesystem::current_path().string() + "/../bb", std::experimental::filesystem::current_path().string() + "/xx"); //文件拷贝
    bool ok = std::experimental::filesystem::remove(std::experimental::filesystem::current_path().string() + "/../dd");
    //编译加上链接参数 -lstdc++fs

    //g++ 9.3以上和windows一样
#endif
	std::cout << "-----------------------------" << std::endl;
    
	//提供any类型,可以创建任意类型的数据
	std::vector<std::any> anyVec{ "chare", 234234, 342.34534, std::pair(342,23), std::tuple(34, "sdf", 3423.232) };
	for (auto &anyValue : anyVec)
	{
		std::cout << anyValue.type().name() << std::endl;
	}
	std::cout << "-----------------------------" << std::endl;
	// //提供variant共用体
	std::variant<int, float> v, w;       //std::variant是共用体union类型
	v = 12;                              // v contains int
	int i = std::get<int>(v);
	w = std::get<int>(v);
	w = std::get<0>(v);                  // same effect as the previous line
	w = v;                               // same effect as the previous line
 
	// std::get<double>(v);               // error: no double in [int, float]
	// std::get<3>(v);                    // error: valid index values are 0 and 1
	try
	{
		float f = std::get<float>(w);    // w contains int, not float: will throw
	}
	catch (std::bad_variant_access&)
	{
	}
	// //determine the type of variant
	if (v.index() == 1) {
		// it's float type
		std::wcout << L"var2 is float type" << std::endl;
	}
	std::variant<std::string> v2("abc"); // converting constructors work when unambiguous
	v2 = "def";
	std::cout << "-----------------------------" << std::endl;                     // converting assignment also works when unambiguous
	// //结构化绑定
	std::map<int, std::string> mapValue{ {32,"fer"}, {343,"erwe"},{2389,"ewr"} };
	for (auto &[key, value] : mapValue) {
		std::cout << key << " "  << value << std::endl;	
	}
	std::vector<std::tuple<int, std::string, std::string>> tupleVec{ {45,"fe","123"},{454,"erw","ewrw"},{898,"fwer","werew"} };
	for (auto &[value1, value2, value3] : tupleVec) {
		std::cout << value1 << " " << value2 << " " << value3 << std::endl;
	}
	// //if语句内置变量声明
	if (int a = std::min(3, 5); a < 9) {
		std::cout << a << " is less than 9" << std::endl;	
	}
	else {
		std::cout << a << " is larger than 9" << std::endl;
	}
	std::set<std::string> stringSet{ "feriji" };
	if (auto[iter, success] = stringSet.insert("aaa"); success) { //insert返回迭代器位置和操作是否成功,结构化绑定到初始变量中
		std::cout << *iter << std::endl; // aaa
	}
	else
	{
		std::cout << "insert failed" << std::endl; // aaa
	}
	// //if constexpr(expression) 编译期对进行判断
	std::cout << sum<1, 2, 3>() << std::endl;
	// //可变参数模板增加折叠表达式 https://www.jianshu.com/p/4bf4d1860588 https://blog.csdn.net/ding_yingzi/article/details/79973809
	std::cout << sum<1, 2, 3>() << std::endl;
	// //增加的STL算法 std::for_each_n, std::exclusive_scan, std::inclusive_scan, std::transfom_exclusive_scan , std::transform_inclusive_scan, std::reduce and std::transform_reduce
	// //std::for_each更新
	// // for_each_n
	std::vector<int> intVec{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };                        // 1
	std::for_each_n(std::execution::par,                       // 2 前n个数进行for_each
		intVec.begin(), 5, [](int& arg) { arg *= arg; });
 
	std::cout << "for_each_n: ";
	for (auto v : intVec) std::cout << v << " ";
	std::cout << "\n\n";
 
	// // exclusive_scan and inclusive_scan
	std::vector<int> resVec{ 4, 2, 3, 4, 5, 6, 7, 8, 9 };
	std::exclusive_scan(std::execution::par,                   // 3
		resVec.begin(), resVec.end(), resVec.begin(), 10, //第一个元素就是初始值10, 从第二个开始依次乘以前面的数,最后一个元素不进行计算;前一次的结果会做为后一次的第一个参数
		[](int fir, int sec) { return fir * sec; });      //10 10*4 10*4*2 10*4*2*3 ... 10*4*2*...*8
 
	std::cout << "exclusive_scan: ";
	for (auto v : resVec) std::cout << v << " ";
	std::cout << std::endl;
 
	std::vector<int> resVec2{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 
	std::inclusive_scan(std::execution::par,                   // 5 
		resVec2.begin(), resVec2.end(), resVec2.begin(), //第一个元素就是初始值10 * resV2的第一个元素, 最后一个元素包含在内进行计算;前一次的结果会做为后一次的第一个参数
		[](int fir, int sec) { return fir * sec; }, 10); //10*1, 10*1*2, 10*1*2*3, .. ,10*1*2*3*...*9
 
	std::cout << "inclusive_scan: ";
	for (auto v : resVec2) std::cout << v << " ";
	std::cout << "\n\n";
 
	// // transform_exclusive_scan and transform_inclusive_scan
	std::vector<int> resVec3{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	std::vector<int> resVec4(resVec3.size());
	std::transform_exclusive_scan(std::execution::par,         // 6
		resVec3.begin(), resVec3.end(),
		resVec4.begin(), 0,
		[](int fir, int sec) { return fir + sec; },
		[](int arg) { return arg *= arg; });
 
	std::cout << "transform_exclusive_scan: ";
	for (auto v : resVec4) std::cout << v << " ";
	std::cout << std::endl;
 
	std::vector<std::string> strVec{ "Only", "for", "testing", "purpose" };             // 7
	std::vector<int> resVec5(strVec.size());
 
	std::transform_inclusive_scan(std::execution::par,         // 8
		strVec.begin(), strVec.end(),
		resVec5.begin(),
		[](auto fir, auto sec) { return fir + sec; },
		[](auto s) { return s.length(); });
 
	std::cout << "transform_inclusive_scan: ";
	for (auto v : resVec5) std::cout << v << " ";
	std::cout << "\n\n";
 
	// reduce and transform_reduce
	std::vector<std::string> strVec2{ "Only", "for", "testing", "purpose" };
 
	std::string res = std::reduce(std::execution::par,         // 9 std::reduce前一次计算的结果,做为后一次的参数
		strVec2.begin() + 1, strVec2.end(), strVec2[0],
		[](auto fir, auto sec) { return fir + ":" + sec; });
 
	std::cout << "reduce: " << res << std::endl;
 
	// 11
	//  std::execution::seq
	//	调用者线程单线程方式,以不确定的顺序访问元素
	//	std::execution::par
	//	多线程(由库隐式的创建线程)方式,在每个线程中,以不确定的顺序访问元素
	//	std::execution::par_unseq
	//	multiple threads and may be vectorized - calls are unsequenced with respect to each other and possibly interleaved
	std::size_t res7 = std::transform_reduce(std::execution::par, //std::execution::par可能会自己创建线程协助完成运算 http://www.cnblogs.com/thomas76/p/8554668.html
		strVec2.begin(), strVec2.end(), size_t(0),
		[](std::size_t a, std::size_t b) { std::cout << "threadId " << std::this_thread::get_id() << std::endl; return a + b; },
		[](std::string s) { return s.length(); }
	);
 
	std::cout << "transform_reduce: " << res7 << std::endl;
    return 0;
	int arr[100000];
	std::for_each(std::execution::par, arr, arr + 10000, [](auto & x) { std::cout << "threadId " << std::this_thread::get_id(); x * 3 / 2 + 5 - 8; }); //根据打印即可看到出现了多个线程,需要考虑加锁或者使用原子变量
 
	//加锁处理
	int a[] = { 0,1,3,4,5,6,7,8,9 };
 
	std::vector<int> vtest;
	std::mutex m;
 
	std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int i) {
		std::lock_guard<std::mutex> guard(m);  //互斥量保护v
		vtest.push_back(i * 2 + 1);
	});
 
    int _tmp[5]={0};
    char __c[3]={0};
    
    //iota c++11就添加了,以做备忘
    std::iota(_tmp, _tmp+5, 10); //changes a to {10,11,12,13,14}
    std::iota(__c, __c+3, 'a'); //{'a','b','c'}
 
	//c++ stl函数说明 https://zh.cppreference.com/w/cpp/algorithm
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值