# C++ 动态新闻推送 第7期

reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。

discord讨论群组 ｜飞书讨论群组｜知乎专栏

## 文章

https://en.cppreference.com/w/cpp/numeric/constants c++20的新功能，可以看这段代码

```#include <cmath>
#include <iomanip>
#include <iostream>
#include <limits>
#include <numbers>
#include <string_view>

struct two_t {};
template <class T>
constexpr auto operator^(T base, two_t) { return base * base; }

int main()
{
using namespace std::numbers;
constexpr two_t ²;

std::cout << "The answer is " <<
(((std::sin(e)^²) + (std::cos(e)^²)) +
std::pow(e, ln2) + std::sqrt(pi) * inv_sqrtpi +
((std::cosh(pi)^²) - (std::sinh(pi)^²)) +
sqrt3 * inv_sqrt3 * log2e * ln2 * log10e * ln10 *
pi * inv_pi + (phi * phi - phi)) *
((sqrt2 * sqrt3)^²) << '\n';

auto egamma_aprox = [] (unsigned const iterations) {
long double s = 0, m = 2.0;
for (unsigned c = 2; c != iterations; ++c, ++m) {
const long double t = std::riemann_zeta(m) / m;
(c & 1) == 0 ? s += t : s -= t;
}
return s;
};

constexpr std::string_view γ {"0.577215664901532860606512090082402"};

std::cout
<< "γ as 10⁶ sums of ±ζ(m)/m   = "
<< egamma_aprox(1'000'000) << '\n'
<< "γ as egamma_v<float>       = "
<< std::setprecision(std::numeric_limits<float>::digits10 + 1)
<< egamma_v<float> << '\n'
<< "γ as egamma_v<double>      = "
<< std::setprecision(std::numeric_limits<double>::digits10 + 1)
<< egamma_v<double> << '\n'
<< "γ as egamma_v<long double> = "
<< std::setprecision(std::numeric_limits<long double>::digits10 + 1)
<< egamma_v<long double> << '\n'
<< "γ with " << γ.length() - 1 << " digits precision = " << γ << '\n';
}
//γ as 10⁶ sums of ±ζ(m)/m   = 0.577215
//γ as egamma_v<float>       = 0.5772157
//γ as egamma_v<double>      = 0.5772156649015329
//γ as egamma_v<long double> = 0.5772156649015328606
//γ with 34 digits precision = 0.577215664901532860606512090082402```

```#pragma once

#include <limits>
#include <type_traits>
#include <stdexcept>
#include <cmath>
#include <cstdint>

// solution 1
// can specify number of digits at run-time as the second parameter
// slowest due to 2 function calls
template<typename T>
requires std::is_floating_point_v<T>
auto runtime_round(T v, unsigned char d)
{
auto p = std::pow(T(10), T(d));
if(std::abs(v) > std::numeric_limits<T>::max() / p) // v * p would overflow
throw std::overflow_error("rounding would overflow");
return std::round(v * p) / p;
}

// sloution 2
// if used only with other constexpr the result will be evaluated
// entirely at compile time meaning no runtime cost :)

// recursive template to compute B^E at compile time
// result is stored as a static variable 'value' of type T
template<std::uint64_t B, unsigned char E, typename T>
requires std::is_arithmetic_v<T>
struct power_of
{
static constexpr T value = T(B) * power_of<B, E - 1, T>::value;
};

// terminating template for the recursion one above once E == 0
template<std::uint64_t B, typename T>
requires std::is_arithmetic_v<T>
struct power_of<B, 0, T>
{
static constexpr T value = T(1);
};

template<std::uint64_t B, unsigned char E, typename T>
inline constexpr auto power_of_v = power_of<B, E, T>::value;

// recursive function template to calculate b^e
// if both parameters are constexpr it will evaluate at compile time
// otherwise it will evaluate at run time
// returns the result as type T
template<typename T>
requires std::is_arithmetic_v<T>
constexpr T power_of_f(std::uint64_t b, unsigned char e)
{
return e == 0 ? T(1) : T(b) * power_of_f<T>(b, e - 1);
}

// given a value 'v' return +1 if v is >= 0, otherwise return -1
template<typename T>
requires std::is_arithmetic_v<T>
constexpr auto my_sign(T v)
{
return v >= T(0) ? T(1) : T(-1);
}

// given a value 'v' return it's absolute value
template<typename T>
requires std::is_arithmetic_v<T>
constexpr auto my_abs(T v)
{
return v >= T(0) ? v : -v;
}

// round float/double/long double value 'v' to the nearest integer
// using compile time type conversions
template<typename T>
requires std::is_floating_point_v<T>
constexpr auto my_rnd(T v)
{
constexpr auto h = T(0.5) - std::numeric_limits<T>::epsilon();
return (std::int64_t)(v + h * my_sign(v));
}

// self explanatory :)
// though number of digits must be provided at compile time
// as the first template parameter 'D'
template<unsigned char D, typename T>
requires std::is_floating_point_v<T>
constexpr auto constexpr_round(T v)
{
/* option 1 */ //constexpr auto p = power_of_f<T>(10, D);
/* option 2 */ constexpr auto p = power_of_v<10, D, T>;
if(my_abs(v) > std::numeric_limits<T>::max() / p)
return v; // v * p would overflow
if(my_abs(v) * p > std::numeric_limits<std::int64_t>::max() - 1)
return v; // v * p would not fit in int64_t
return my_rnd(v * p) / p;
}```

```// startJob.cpp

#include <coroutine>
#include <iostream>

struct Job {
struct promise_type;
using handle_type = std::coroutine_handle<promise_type>;
handle_type coro;
Job(handle_type h): coro(h){}
~Job() {
if ( coro ) coro.destroy();
}
void start() {
coro.resume();                                    // (6)
}

struct promise_type {
auto get_return_object() {
return Job{handle_type::from_promise(*this)};
}
std::suspend_always initial_suspend() {           // (4)
std::cout << "    Preparing job" << '\n';
return {};
}
std::suspend_always final_suspend() noexcept {    // (7)
std::cout << "    Performing job" << '\n';
return {};
}
void return_void() {}
void unhandled_exception() {}

};
};

Job prepareJob() {                                        // (1)
co_await std::suspend_never();                        // (2)
}

int main() {

std::cout <<  "Before job" << '\n';

auto job = prepareJob();                              // (3)
job.start();                                          // (5)

std::cout <<  "After job" <<  '\n';

}
//打印
//Before job
//    Preparing job
//    Performing job
//After job```
```#include <coroutine>
#include <iostream>
#include <optional>
#include <string_view>
#include <vector>

template <typename T> struct future {
struct promise_type {
T value;
future get_return_object() {
return {std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_always initial_suspend() noexcept {
std::cout << "initial" << std::endl;
return {};
}
std::suspend_always final_suspend() noexcept {
std::cout << "final" << std::endl;
return {};
}
void return_value(T x) {
std::cout << "return value" << std::endl;
value = std::move(x);
}
void unhandled_exception() noexcept {}

~promise_type() { std::cout << "future ~promise_type" << std::endl; }
};

struct AwaitableFuture {
future &m_future;
bool await_ready() const noexcept { return false; }

void await_suspend(std::coroutine_handle<> handle) {
std::cout << "await_suspend" << std::endl;
<< std::endl;
m_future.coro.resume();
handle.resume();
});
}

T await_resume() {
std::cout << "await_resume" << std::endl;
return m_future.coro.promise().value;
}

~AwaitableFuture() { std::cout << "~AwaitableFuture" << std::endl; }
};

std::coroutine_handle<promise_type> coro;

future(std::coroutine_handle<promise_type> coro) : coro{coro} {}

~future() {
std::cout << "~future" << std::endl;
if (coro)
coro.destroy();
}

AwaitableFuture operator co_await() {
std::cout << "co_await" << std::endl;
return {*this};
}
};

template <typename F, typename... Args>
future<std::invoke_result_t<F, Args...>> async(F f, Args... args) {
std::cout << "async" << std::endl;
co_return f(args...);
}

struct promise_type {
task get_return_object() { return {}; }
std::suspend_never initial_suspend() noexcept { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() noexcept {}
~promise_type() { std::cout << "~task promise_type" << std::endl; }
};

};

int square(int x) {
<< std::endl;
return x * x;
}

auto squared6 = co_await async(square, 6);

std::cout << "Write " << squared6
}

int main() {

f();

return 0;
}```

```#include <string>
#include <string_view>

// Some type that is expensive to copy, non-trivial to destroy, and cheap but
// not free to move.
struct Widget {
std::string s;
};

void consume(Widget w);

Widget doSomeVeryComplicatedThingWithSeveralArguments(
int arg1, std::string_view arg2);

//正常，一个widget，RVO
void someFunction() {
consume(doSomeVeryComplicatedThingWithSeveralArguments(123, "hello"));
}

//没优化，复制了一份？？？？
void someFunctionV2() {
auto complicatedThingResult =
doSomeVeryComplicatedThingWithSeveralArguments(123, "hello");
consume(complicatedThingResult);
}

//还是没优化？？
void someFunctionV3() {
auto complicatedThingResult =
doSomeVeryComplicatedThingWithSeveralArguments(123, "hello");
consume(std::move(complicatedThingResult));
}

//优化了，但这里没有临时的widget，是通过lambda绕过去的
void someFunctionV4() {
auto const complicatedThingResult  = []{
return
doSomeVeryComplicatedThingWithSeveralArguments(
123, "hello"
);
};
consume(complicatedThingResult());
}```

```template <class... Fs> struct overloaded;

template <class F1> struct overloaded<F1> : F1 {
using F1::operator();
};

template <class F1, class... Fs>
using F1::operator();
};

template <typename... Fs>
};```
```class app {
public:
explicit(true) app(int, double) { }
};

struct config : boost::di::config {
struct mocks {
template <class T, class TInitialization, class TMemory, class... TArgs>
auto get(const TInitialization&, const TMemory&, TArgs&&... args) const
-> boost::di::aux::owner<T*> {
std::clog << typeid(T).name() << '\n';
return new T{args...};
}
};

auto provider(...) const { return mocks{}; }
};

int main() {
boost::di::create<app>(boost::di::make_injector<config>());
// prints app
//                                                                      int
//                                                                     double
}```

```namespace vast {
std::vector<std::pair<offset, predicate>> resolve(const expression& expr, const type& t);
}```

```struct vector {
void* first;
void* last;
void* end_of_storage;
};

uretprobe:/usr/bin/vast:_ZN4vast7resolveERKNS_10expressionERKNS_4typeE {
\$vec = (struct vector*)reg("ax");
printf("resolved %d offset+predicate pairs\n", (\$vec->last - \$vec->first) / 464);
}```

```PROBE {
ACTION_BLOCK
}```

```sudo bpftrace simple.bt
Attaching 1 probe...
resolved 5 offset+predicate pairs
resolved 7 offset+predicate pairs```

mozilla firefox团队使用tsan的经验总结。值得一看，rust一样会被tsan抓到问题

``` cat tests/uninit_read.c
* Copyright 2021 - chris.rohlf@gmail.com */

#include "iso_alloc.h"
#include "iso_alloc_internal.h"

int main(int argc, char *argv[]) {
while(1) {
uint8_t *p = iso_alloc(1024);
uint8_t drf = p[128];
p[256] = drf;
iso_free(p);
}

return OK;
}

Aborted (core dumped)```

isoalloc设计就是为了内存安全的，考虑了很多点子，可以了解一下。对于实际的写代码的人，用MSan就好了

```static inline constexpr unsigned long long int x = 42;
long int long inline unsigned constexpr static y = 42;```

## 项目

• https://github.com/fschuetz04/simcpp20 一个simpy的c++实现，使用coroutine

0 条评论

• ### C++ 动态新闻推送 第35期

怎么保证一个函数只被调用一次呢，这里有个点子，Destructive separation: move away and call Matt Godbolt a...

• ### C++ 动态新闻推送 第34期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态

• ### C++ 动态新闻推送 第33期

很多代码场景下c++的灵活性要高于强制安全检查，且一些场景下rust生成的汇编不如c++少

• ### C++ 动态新闻推送 第32期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态

• ### C++ 动态新闻推送 第31期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态

• ### C++ 动态新闻推送 第30期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。

• ### C++ 动态新闻推送 第20期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。

• ### C++ 动态新闻推送 第15期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。

• ### C++ 动态新闻推送 第14期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。

• ### C++ 动态新闻推送 第5期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。

• ### C++ 动态新闻推送 第4期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。

• ### C++ 动态新闻推送 第3期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。

• ### C++ 动态新闻推送 第2期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。

• ### C++ 动态新闻推送 第19期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。

• ### C++ 动态新闻推送 第18期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。

• ### C++ 动态新闻推送 第17期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。

• ### C++ 动态新闻推送 第13期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。

• ### C++ 动态新闻推送 第11期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。

• ### C++ 动态新闻推送 第10期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。