C++现代教程五
#pragma once _Pragma("once") # C/C++混合编程 #ifdef __cplusplus extern "C" { #endif // 一些c代码 #ifdef __cplusplus } #endif # 继承构造 struct A { A(int i) {} A(double d,int i){} A(float f,int i,const char* c){} //...等等系列的构造函数版本 }; old: struct B:A { B(int i):A(i){} B(double d,int i):A(d,i){} B(folat f,int i,const char* c):A(f,i,e){} //......等等好多个和基类构造函数对应的构造函数 }; new: struct B:A { using A::A; //关于基类各构造函数的继承一句话搞定 //...... }; #regex std::regex base_regex("([a-z]+)\\.txt"); std::smatch base_match; for(const auto &fname: fnames) { if (std::regex_match(fname, base_match, base_regex)) { // sub_match 的第一个元素匹配整个字符串 // sub_match 的第二个元素匹配了第一个括号表达式 if (base_match.size() == 2) { std::string base = base_match[1].str(); std::cout << "sub-match[0]: " << base_match[0].str() << std::endl; std::cout << fname << " sub-match[1]: " << base << std::endl; } } } #Variadic templates // C++11 template <typename First, typename... Args> auto sum(const First first, const Args... args) -> decltype(first) { const auto values = {first, args...}; return std::accumulate(values.begin(), values.end(), First{0}); } // C++17 template <typename... Args> auto sum(Args... args) { // Unary folding. return (... + args); } template <typename... Args> bool logicalAnd(Args... args) { // Binary folding. return (true && ... && args); } bool b = true; bool& b2 = b; logicalAnd(b, b2, true); // == true #Inline namespaces namespace Program { namespace Version1 { int getVersion() { return 1; } bool isFirstVersion() { return true; } } inline namespace Version2 { int getVersion() { return 2; } } } int version {Program::getVersion()}; // Uses getVersion() from Version2 int oldVersion {Program::Version1::getVersion()}; // Uses getVersion() from Version1 bool firstVersion {Program::isFirstVersion()}; // Does not compile when Version2 is added # std::move temp struct Bar { int a = 1; }; struct Foo { Bar getBar() & { return bar; } Bar getBar() const& { return Bar{}; } Bar getBar() && { return std::move(Bar{}); } private: Bar bar; }; Foo foo; auto&& ref = foo.getBar(); ref.a = 10; # Nested namespaces namespace A::B::C { int i; } # __has_include #ifdef __has_include # if __has_include(<optional>) # include <optional> # define have_optional 1 # elif __has_include(<experimental/optional>) # include <experimental/optional> # define have_optional 1 # define experimental_optional # else # define have_optional 0 # endif #endif # std::invoke template <typename Callable> class Proxy { Callable c_; public: Proxy(Callable c) : c_{ std::move(c) } {} template <typename... Args> decltype(auto) operator()(Args&&... args) { // ... return std::invoke(c_, std::forward<Args>(args)...); } }; const auto add = [](int x, int y) { return x + y; }; Proxy p{ add }; p(1, 2); // == 3 # std::clamp limitRange std::clamp(0, -1, 1, std::less<>{}); // == 0 # std::reduce const std::array<int, 3> a{ 1, 2, 3 }; std::reduce(std::cbegin(a), std::cend(a)); // == 6 default binary operation is std::plus // Using a custom binary op: std::reduce(std::cbegin(a), std::cend(a), 1, std::multiplies<>{}); // == 6 const std::array<int, 3> b{ 1, 2, 3 }; const auto product_times_ten = [](const auto a, const auto b) { return a * b * 10; }; std::transform_reduce(std::cbegin(a), std::cend(a), std::cbegin(b), 0, std::plus<>{}, product_times_ten); // == 140 # std::inclusive_scan const std::array<int, 3> a{ 1, 2, 3 }; std::inclusive_scan(std::cbegin(a), std::cend(a), std::ostream_iterator<int>{ std::cout, " " }, std::plus<>{}); // 1 3 6 std::exclusive_scan(std::cbegin(a), std::cend(a), std::ostream_iterator<int>{ std::cout, " " }, 0, std::plus<>{}); // 0 1 3 const auto times_ten = [](const auto n) { return n * 10; }; std::transform_inclusive_scan(std::cbegin(a), std::cend(a), std::ostream_iterator<int>{ std::cout, " " }, std::plus<>{}, times_ten); // 10 30 60 std::transform_exclusive_scan(std::cbegin(a), std::cend(a), std::ostream_iterator<int>{ std::cout, " " }, 0, std::plus<>{}, times_ten); // 0 10 30 # GCD and LCM 公倍数 const int p = 9; const int q = 3; std::gcd(p, q); // == 3 std::lcm(p, q); // == 9 # std::not_fn # C++20 Coroutines generator<int> range(int start, int end) { while (start < end) { co_yield start; start++; } // Implicit co_return at the end of this function: // co_return; } for (int n : range(0, 10)) { std::cout << n << std::endl; } # concept template <typename T> concept unsigned_integral = integral<T> && !signed_integral<T>; template <typename T> concept callable = requires (T f) { f(); }; // `T` is a constrained type template parameter. template <typename T> requires my_concept<T> void f(T v); # [[likely]] and [[unlikely]] attributes switch (n) { case 1: // ... break; [[likely]] case 2: // n == 2 is considered to be arbitrarily more // ... // likely than any other value of n break; } int random = get_random_number_between_x_and_y(0, 3); if (random > 0) [[likely]] { // body of if statement // ... } # constexpr virtual functions struct X1 { virtual int f() const = 0; }; struct X2: public X1 { constexpr virtual int f() const { return 2; } }; # explicit(bool) struct foo { // Specify non-integral types (strings, floats, etc.) require explicit construction. template <typename T> explicit(!std::is_integral_v<T>) foo(T) {} }; # enum enum class rgba_color_channel { red, green, blue, alpha }; std::string_view to_string(rgba_color_channel my_channel) { switch (my_channel) { using enum rgba_color_channel; case red: return "red"; case green: return "green"; case blue: return "blue"; case alpha: return "alpha"; } } # constinit const char* g() { return "dynamic initialization"; } constexpr const char* f(bool p) { return p ? "constant initializer" : g(); } constinit const char* c = f(true); // OK constinit const char* d = f(false); // ERROR: `g` is not constexpr, so `d` cannot be evaluated at compile-time. # std::span std::span<const int, 3>{ c.cbegin(), c.cend() } # Bit operations std::popcount(0u); // 0 std::popcount(1u); // 1 std::popcount(0b1111'0000u); // 4 # Math constants std::numbers::pi; // 3.14159... std::numbers::e; // 2.71828.. # starts_with and ends_with on strings std::string str = "foobar"; str.starts_with("foo"); // true str.ends_with("baz"); // false # std::midpoint std::midpoint(1, 3); // == 2 # std::to_array int a[] = {1, 2, 3}; std::to_array(a); // returns `std::array<int, 3>`C++现代教程四_c++ float 转 string-CSDN博客