#include
#ifdef __has_cpp_attribute
#if __has_cpp_attribute(deprecated)
#define DEPRECATED(msg) [[deprecated(msg)]]
#endif
#endif
#ifndef DEPRECATED
#define DEPRECATED
#endif
DEPRECATED("the func has been deprecated")
void func()
{
std::cout << "test";
}
int main()
{
func();
getchar();
return 0;
}
#include
#include
int main()
{
double foo = -0.0;
double bar = 0.0;
auto res = foo <=> bar;
if (res < 0)
std::cout << "-0 is less than 0";
else if (res > 0)
std::cout << "-0 is greater than 0";
else // (res == 0)
std::cout << "-0 and 0 are equal";
}
//输出结果:-0 and 0 are equal
struct test
{
int a;
int b;
};
int main()
{
test t{ .b = 10, .a = 20 };//error
test t{ .a = 10, .b = 20 };
return 0;
}
#include
struct Empty {}; // empty class
struct X {
int i;
Empty e;
};
struct Y {
int i;
[[no_unique_address]] Empty e;
};
struct Z {
char c;
[[no_unique_address]] Empty e1, e2;
};
struct W {
char c[2];
[[no_unique_address]] Empty e1, e2;
};
if(x)[[likely]]
{
std::cout << 1;
}
else[[unlikely]]
{
std::cout << 2;
}
constexpr unsigned factorial(unsigned n) {
return n < 2 ? 1 : n * factorial(n - 1);
}
consteval unsigned combination(unsigned m, unsigned n) {
return factorial(n) / factorial(m) / factorial(n - m);
}
static_assert(factorial(6) == 720);
static_assert(combination(4,8) == 70);
int main(int argc, const char*[]) {
constexpr unsigned x{factorial(4)};
std::cout << x << '\n';
[[maybe_unused]]
unsigned y = factorial(argc); // OK
// unsigned z = combination(argc, 7); // error: 'argc' 不是一个常量表达式
}
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
#include
#include
//编译环境 vs2017
struct generator
{
struct promise_type;
using handle = std::experimental::coroutine_handle<promise_type>;
struct promise_type
{
static auto get_return_object_on_allocation_failure() { return generator(nullptr); }
auto get_return_object() { return generator{ handle::from_promise(*this) }; }
auto initial_suspend() { return std::experimental::suspend_always{}; }
auto final_suspend() { return std::experimental::suspend_always{}; }
void unhandled_exception() { std::terminate(); }
void return_void() {}
//auto return_value(int value) { return value; }
};
bool move_next() { return coro ? (coro.resume(), !coro.done()) : false; }
int current_value() { return coro.promise().current_value; }
generator(generator const &) = delete;
generator(generator &&rhs) : coro(rhs.coro) { rhs.coro = nullptr; }
~generator() { if (coro) coro.destroy(); }
private:
generator(handle h) : coro(h) {}
handle coro;
};
generator f()
{
std::cout << "hello";
co_await std::experimental::suspend_always();
std::cout << "world";
}
int main()
{
auto ret = f();
while (ret.move_next())
{
std::cout << " ";
}// hello world
getchar();
return 0;
}
// A.cpp
export module A;
export import :B;
import :C;
export char const* World() {
return WorldImpl();
}
// A-B.cpp
export module A:B;
export char const* Hello() { return "Hello"; }
// A-C.cpp
module A:C;
char const* WorldImpl() { return "World"; }
// main.cpp
import A;
import ;
int main()
{
std::cout << Hello() << ' ' << World() << '\n';
}
template<typename T>
concept Addable = requires (T obj) {{obj + obj}->std::same_as<T>;};//约束a+b的类型必须和T类型一致
T add(T a, T b)
{
return a + b;
}
#include
#include
int main() {
std::string message = std::format("The answer is {}.", 42);//The answer is 42.
std::string buffer;
std::format_to(std::back_inserter(buffer), "Hello, C++{}!\n", "20");//向后插入,Hello, C++20!
auto buff = "{0}:{1}:{2}";
auto h = 17;
auto m = 46;
auto s = 55;
auto size = std::format_size(buff, h, m, s);
std::string ti;
ti.resize(size);
std::format_to_n(const_cast<char*>(ti.c_str()), ti.size(), buff, h, m, s);
ti.push_back('\0');//17:46:55
}
#include
#include
long fibonacci(unsigned n)
{
if (n < 2) return n;
return fibonacci(n-1) + fibonacci(n-2);
}
int main()
{
auto start = std::chrono::steady_clock::now();
std::cout << "f(42) = " << fibonacci(42) << '\n';
auto end = std::chrono::steady_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n";
//elapsed time: 1.88232s
}
#include
#include
#include
void log(const std::string_view message,
const std::source_location location =
std::source_location::current())
{
std::cout << "file: "
<< location.file_name() << "("
<< location.line() << ":"
<< location.column() << ") `"
<< location.function_name() << "`: "
<< message << '\n';
}
template <typename T> void fun(T x)
{
log(x);
}
int main(int, char*[])
{
log("Hello world!");//file: main.cpp(24:8) `int main(int, char**)`: Hello world!
fun("Hello C++20!");//file: main.cpp(19:8) `void fun(T) [with T = const char*]`: Hello C++20!
}
#include
#include
template<class T, std::size_t N> [[nodiscard]]
constexpr auto slide(std::span<T,N> s, std::size_t offset, std::size_t width)
{
return s.subspan(offset, offset + width <= s.size() ? width : 0U);
}
void print(const auto& seq)
{
for (const auto& elem : seq) std::cout << elem << ' ';
std::cout << '\n';
}
int main()
{
constexpr int a[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
for (std::size_t offset{}; ; ++offset)
{
static constexpr std::size_t width{6};
auto s = slide(std::span{a}, offset, width);
if (s.empty())
break;
print(s);
}
}
#include
#include
int main()
{
if constexpr (std::endian::native == std::endian::big)
std::cout << "big-endian\n";
else if constexpr (std::endian::native == std::endian::little)
std::cout << "little-endian\n";
else std::cout << "mixed-endian\n";
}
std::shared_ptr<float[512]> spA = std::make_shared<float[512]>(1.0);
std::shared_ptr<double[6][2]> spB = std::make_shared<double[6][2]>({1.0, 2.0});
std::shared_ptr<std::vector<int>[4]> spC = std::make_shared<std::vector<int>[4]>({5, 6});
#include
#include
int main()
{
std::cout << std::boolalpha
<< std::is_same_v<std::remove_cvref_t<int>, int> << '\n'
<< std::is_same_v<std::remove_cvref_t<int&>, int> << '\n'
<< std::is_same_v<std::remove_cvref_t<int&&>, int> << '\n'
<< std::is_same_v<std::remove_cvref_t<const int&>, int> << '\n'
<< std::is_same_v<std::remove_cvref_t<const int[2]>, int[2]> << '\n'
<< std::is_same_v<std::remove_cvref_t<const int(&)[2]>, int[2]> << '\n'
<< std::is_same_v<std::remove_cvref_t<int(int)>, int(int)> << '\n';
}
/*
true
true
true
true
true
true
true
*/
#include
#include
int main()
{
std::shared_ptr<int> a(new int{0});
std::cout << a.get() << " " << std::to_address(a);
//0x493eb0 0x493eb0
return 0;
}
#include
#include
#include
int main()
{
std::vector<int> v = { 3, 1, 4 };
std::cout << std::size(v) << '\n';
int a[] = { -5, 10, 15 };
std::cout << std::size(a) << '\n';
// since C++20 the signed size (ssize) can avail
auto i = std::ssize(v);
std::cout << "i = " << i << '\n';
for (--i; i != -1; --i) {
std::cout << v[i] << (i ? ' ' : '\n');
}
std::cout << "i = " << i << '\n';
}
/*
3
3
i = 3
4 1 3
i = -1
*/
#include
#include
#include
#include
#include
int main()
{
struct job
{
const std::string name;
std::string product{"not worked"};
std::thread action{};
} jobs[] = {{"annika"}, {"buru"}, {"chuck"}};
std::latch work_done{std::size(jobs)};
std::latch start_clean_up{1};
auto work = [&](job& my_job)
{
my_job.product = my_job.name + " worked";
work_done.count_down();//执行完毕
start_clean_up.wait();//等待
my_job.product = my_job.name + " cleaned";
};
std::cout << "Work starting... ";
for (auto& job : jobs)
{
job.action = std::thread{work, std::ref(job)};
}
work_done.wait();//同步等待执行完毕
std::cout << "done:\n";
for (auto const& job : jobs)
{
std::cout << " " << job.product << '\n';
}
std::cout << "Workers cleaning up... ";
start_clean_up.count_down();//通知可以继续了
for (auto& job : jobs)
{
job.action.join();//join等待线程执行完毕
}
std::cout << "done:\n";
for (auto const& job : jobs)
{
std::cout << " " << job.product << '\n';
}
}
/*
Work starting... done:
annika worked
buru worked
chuck worked
Workers cleaning up... done:
annika cleaned
buru cleaned
chuck cleaned
*/
-类模板std::barrier提供了一种线程协调机制,该机制最多允许预期数量的线程阻塞,直到预期数量的线程到达屏障。与std::latch不同,屏障是可重用的:一旦到达的线程从屏障阶段的同步点解除阻塞,就可以重用相同的屏障
#include
#include
#include
#include
#include
int main()
{
const auto workers = { "anil", "busara", "carl" };
auto on_completion = []() noexcept
{
// locking not needed here
static auto phase = "... done\nCleaning up...\n";
std::cout << phase;
phase = "... done\n";// 第一遍执行完后phase就改变了值
};
std::barrier sync_point(std::ssize(workers), on_completion);
auto work = [&](std::string name)
{
std::string product = " " + name + " worked\n";
std::cout << product; // 3个线程先执行到这儿,然后执行一遍on_completion
sync_point.arrive_and_wait();
product = " " + name + " cleaned\n";
std::cout << product;// 然后到这儿,再执行一遍on_completion
sync_point.arrive_and_wait();// 将此句删除就不会再执行第二遍的on_completion
};
std::cout << "Starting...\n";
std::vector<std::thread> threads;
for (auto const& worker : workers)
{
threads.emplace_back(work, worker);
}
for (auto& thread : threads)
{
thread.join();
}
}
/*
Starting...
anil worked
busara worked
carl worked
... done
Cleaning up...
carl cleaned
busara cleaned
anil cleaned
... done
*/
#include
#include
#include
#include
std::binary_semaphore
smphSignalMainToThread{0},
smphSignalThreadToMain{0};
void ThreadProc()
{
smphSignalMainToThread.acquire();//得到 -1
std::cout << "[thread] Got the signal\n";
using namespace std::literals;
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "[thread] Send the signal\n";
smphSignalThreadToMain.release();
}
int main()
{
std::thread thrWorker(ThreadProc);
std::cout << "[main] Send the signal\n";
smphSignalMainToThread.release();//+1
smphSignalThreadToMain.acquire();
std::cout << "[main] Got the signal\n";
thrWorker.join();
}
/*
[main] Send the signal
[thread] Got the signal
[thread] Send the signal
[main] Got the signal
*/
#include
#include
#include
#include
std::counting_semaphore<3>
smphSignalMainToThread{0},
smphSignalThreadToMain{0};
void ThreadProc1()
{
smphSignalMainToThread.acquire();
std::cout << "[thread] Got the signal1\n";
using namespace std::literals;
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "[thread] Send the signal1\n";
smphSignalThreadToMain.release();
}
void ThreadProc2()
{
smphSignalMainToThread.acquire();
std::cout << "[thread] Got the signal2\n";
using namespace std::literals;
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "[thread] Send the signal2\n";
smphSignalThreadToMain.release();
}
void ThreadProc3()
{
smphSignalMainToThread.acquire();
std::cout << "[thread] Got the signal3\n";
using namespace std::literals;
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "[thread] Send the signal3\n";
smphSignalThreadToMain.release();
}
int main()
{
std::thread thrWorker1(ThreadProc1);
std::thread thrWorker2(ThreadProc2);
std::thread thrWorker3(ThreadProc3);
std::cout << "[main] Send the signal\n";
smphSignalMainToThread.release(3);
smphSignalThreadToMain.acquire();
std::cout << "[main] Got the signal\n";
thrWorker1.join();
thrWorker2.join();
thrWorker3.join();
}
/*
[main] Send the signal
[thread] Got the signal1
[thread] Got the signal2
[thread] Got the signal3
[thread] Send the signal3
[thread] Send the signal2
[thread] Send the signal1
[main] Got the signal
*/
#include
#include
#include
#include
int main()
{
auto fn = [&](std::stop_token st)
{
while(!st.stop_requested())
{
std::cout << 1 << "\t";
std::this_thread::sleep_for(std::chrono::seconds(1));
}
};
std::jthread td(fn);
std::this_thread::sleep_for(std::chrono::seconds(3));
td.request_stop();//如果没有这句话在main函数结束时析构td也会自动调用停止
return 0;
}
#include
#include
int main()
{
#if 1
std::osyncstream sync_out(std::cout); // std::cout 的同步包装
sync_out << "Hello, ";
sync_out << "World!";
sync_out << std::endl; // 注意有冲入,但仍未进行
sync_out << "and more!\n";
#else
std::osyncstream(std::cout) << "Hello, " << "World!" << '\n';
#endif
return 0;
} // 转移字符并冲入 std::cout
/*
Hello, World!
and more!
*/
#include
#include
#include
template <typename PrefixType>
void test_prefix_print(const std::string& str, PrefixType prefix)
{
std::cout << '\'' << str << "' starts with '" << prefix << "': " <<
str.starts_with(prefix) << '\n';
}
int main()
{
std::boolalpha(std::cout);
auto helloWorld = std::string("hello world");
test_prefix_print(helloWorld, std::string_view("hello"));
test_prefix_print(helloWorld, std::string_view("world"));
test_prefix_print(helloWorld, 'h');
test_prefix_print(helloWorld, 'd');
}
/*
'hello world' starts with 'hello': true
'hello world' starts with 'world': false
'hello world' starts with 'h': true
'hello world' starts with 'd': false
*/
上方starts_with换成ends_with,输出结果为:
'hello world' starts with 'hello': false
'hello world' starts with 'world': true
'hello world' starts with 'h': false
'hello world' starts with 'd': true
#include
#include
auto main() -> int
{
using namespace std::literals;
std::cout
<< std::boolalpha
<< "https://cppreference.com"sv.starts_with("http"sv) << ' ' // true
<< "https://cppreference.com"sv.starts_with("ftp"sv) << ' ' // false
<< "C++20"sv.starts_with('C') << ' ' // true
<< "C++20"sv.starts_with('J') << ' ' // false
<< std::string_view("string_view").starts_with("string") << ' ' // true
<< std::string_view("string_view").starts_with("String") << ' ' // false
<< '\n';
}
void f(int* p) {
int* p1 = std::assume_aligned<256>(p);
// 用 p1 而非 p ,以确保从对齐假设受益。
// 然而,若 p 未对齐则程序有未定义行为,无关乎是否使用 p1 。
}
#include
#include
int minus(int a, int b){
return a-b;
}
struct S
{
int val;
int minus(int arg) const noexcept { return val - arg; }
};
int main()
{
auto fifty_minus = std::bind_front(minus, 50);
std::cout << fifty_minus (3) << '\n';
auto member_minus = std::bind_front(&S::minus, S{50});
std::cout << member_minus (3) << '\n';
// 保持 noexcept 说明!
static_assert(! noexcept(fifty_minus (3)));
static_assert(noexcept(member_minus (3)));
// 绑定 lambda
auto plus = [](int a, int b) { return a+b; };
auto forty_plus = std::bind_front(plus, 40);
std::cout << forty_plus(7) << '\n';
}
#include
#include
#include
#include
int main()
{
auto on_pointers = [](int i, int j) {
char const* text = "0123456789";
char const* p = text + i;
char const* q = text + j;
std::cout << "std::midpoint('" << *p << "', '" << *q << "'): '"
<< *std::midpoint(p, q) << "'\n";
};
on_pointers(2, 4);
on_pointers(2, 5);
on_pointers(5, 2);
on_pointers(2, 6);
return 0;
}
/*
std::midpoint('2', '4'): '3'
std::midpoint('2', '5'): '3'
std::midpoint('5', '2'): '4'
std::midpoint('2', '6'): '4'
*/
#include
#include
int main()
{
float a=10.0f, b=20.0f;
std::cout << "a=" << a << ", " << "b=" << b << '\n'
<< "mid point=" << std::lerp(a,b,0.5f) << '\n'
<< std::boolalpha << (a == std::lerp(a,b,0.0f)) << ' '
<< std::boolalpha << (b == std::lerp(a,b,1.0f)) << '\n';
return 0;
}
/*
a=10, b=20
mid point=15
true true
*/
#include
#include
class A {};
int main()
{
std::cout << std::boolalpha;
std::cout << std::is_bounded_array_v<A> << '\n'; // false
std::cout << std::is_bounded_array_v<A[]> << '\n'; // false
std::cout << std::is_bounded_array_v<A[3]> << '\n'; // true
std::cout << std::is_bounded_array_v<float> << '\n'; // false
std::cout << std::is_bounded_array_v<int> << '\n'; // false
std::cout << std::is_bounded_array_v<int[]> << '\n'; // false
std::cout << std::is_bounded_array_v<int[3]> << '\n'; // true
std::cout << std::boolalpha;
std::cout << std::is_unbounded_array_v<A> << '\n'; // false
std::cout << std::is_unbounded_array_v<A[]> << '\n'; // true
std::cout << std::is_unbounded_array_v<A[3]> << '\n'; // false
std::cout << std::is_unbounded_array_v<float> << '\n'; // false
std::cout << std::is_unbounded_array_v<int> << '\n'; // false
std::cout << std::is_unbounded_array_v<int[]> << '\n'; // true
std::cout << std::is_unbounded_array_v<int[3]> << '\n'; // false
return 0;
}
#include
#include
int main()
{
auto const ints = {0,1,2,3,4,5};
auto even = [](int i) { return 0 == i % 2; };
auto square = [](int i) { return i * i; };
// 组合视图的“管道”语法:
for (int i : ints | std::views::filter(even) | std::views::transform(square)) {
std::cout << i << ' ';
}
std::cout << '\n';
// 传统的“函数式”组合语法:
for (int i : std::views::transform(std::views::filter(ints, even), square)) {
std::cout << i << ' ';
}
} // 0 4 16
#include
#include
#include
void print_container(const std::vector<char>& c)
{
for (auto x : c) {
std::cout << x << ' ';
}
std::cout << '\n';
}
int main()
{
std::vector<char> cnt(10);
std::iota(cnt.begin(), cnt.end(), '0');
std::cout << "Init:\n";
print_container(cnt);// 0 1 2 3 4 5 6 7 8 9
auto erased = std::erase(cnt, '3');
std::cout << "Erase \'3\':\n";
print_container(cnt);// 0 1 2 4 5 6 7 8 9
std::erase_if(cnt, [](char x) { return (x - '0') % 2 == 0; });
std::cout << "Erase all even numbers:\n";
print_container(cnt);// 1 5 7 9
std::cout << "In all " << erased << " even numbers were erased.\n";// 5
}
#include
#include
#include
#include
#include
#include
int main()
{
using namespace std::numbers;
std::cout
<< std::pow(e, ln2) / 2 << ' '
<< std::pow(std::cosh(pi), 2) - std::pow(std::sinh(pi), 2) << ' '
<< std::sqrt(pi) * inv_sqrtpi << ' '
<< std::pow(sqrt2 * sqrt3, 2) / 6 << ' '
<< sqrt3 * inv_sqrt3 << ' '
<< log2e * ln2 << ' '
<< log10e * ln10 << ' '
<< pi * inv_pi << ' '
<< phi * phi - phi << '\n';
auto egamma_aprox = [] {
long double s = 0, m = 2.0;
for (unsigned c = 2; c != 1'000'000; ++c, ++m) {
const long double t = std::riemann_zeta(m) / m;
(c & 1) == 0 ? s += t : s -= t;
}
return s;
};
std::cout << std::fixed << (egamma_v<long double> - egamma_aprox()) << '\n';
constexpr std::string_view γ {"0.577215664901532860606512090082402"};
std::cout
<< "γ as egamma_v = "
<< std::setprecision(std::numeric_limits<float>::digits10 + 1)
<< egamma_v<float> << '\n'
<< "γ as egamma_v = "
<< std::setprecision(std::numeric_limits<double>::digits10 + 1)
<< egamma_v<double> << '\n'
<< "γ as egamma_v = "
<< std::setprecision(std::numeric_limits<long double>::digits10 + 1)
<< egamma_v<long double> << '\n'
<< "γ with " << γ.length() - 1 << " digits precision = " << γ << '\n';
return 0;
}
/*
1 1 1 1 1 1 1 1 1
0.000001
γ as egamma_v = 0.5772157
γ as egamma_v = 0.5772156649015329
γ as egamma_v = 0.5772156649015328606
γ with 34 digits precision = 0.577215664901532860606512090082402
*/