#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;
//提供文件系统管理
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()))
{
std::cout << p.is_directory() << " " << p.path() << std::endl;
}
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; }, 1); //1*1, 1*1*2, 1*1*2*3, .. ,1*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(), 0u,
[](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;
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);
});
//c++ stl函数说明 https://zh.cppreference.com/w/cpp/algorithm
return 0;
}
|