layout | title |
---|---|
post |
第19期 |
从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。
每周更新
欢迎投稿,推荐或自荐文章/软件/资源等,请提交 issue
c++标准委员会六月汇总 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/#mailing2021-06
visit的基本用法
include <iostream>
#include <variant>
struct Fluid { };
struct LightItem { };
struct HeavyItem { };
struct FragileItem { };
template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
template<class... Ts> overload(Ts...) -> overload<Ts...>; // line not needed in C++20...
std::variant<Fluid, LightItem, HeavyItem, FragileItem> package;
std::visit(overload{
[](Fluid& ) { std::cout << "fluid\n"; },
[](LightItem& ) { std::cout << "light item\n"; },
[](HeavyItem& ) { std::cout << "heavy item\n"; },
[](FragileItem& ) { std::cout << "fragile\n"; }
}, package);
除此之外还有一种特别用法,多个variant
std::variant<LightItem, HeavyItem> basicPackA;
std::variant<LightItem, HeavyItem> basicPackB;
std::visit(overload{
[](LightItem&, LightItem& ) { cout << "2 light items\n"; },
[](LightItem&, HeavyItem& ) { cout << "light & heavy items\n"; },
[](HeavyItem&, LightItem& ) { cout << "heavy & light items\n"; },
[](HeavyItem&, HeavyItem& ) { cout << "2 heavy items\n"; },
}, basicPackA, basicPackB);
我觉得没人用这玩意。我看着眼睛疼
编译期探测代码,还是sfinae哪套, 在线点这里
#include <iostream>
#include <string>
#include <type_traits>
#define FWD(x) std::forward<decltype(x)>(x)
#define typed_static_assert(x) static_assert(decltype(x)::value)
template <typename F> std::false_type is_valid_impl(...);
template <typename F, typename... Xs>
constexpr auto is_valid_impl(Xs &&... xs)
-> decltype(std::declval<F>()(FWD(xs)...), void(), std::true_type());
template <typename F> constexpr auto is_valid_f(F) {
return [](auto &&... xs) -> decltype(is_valid_impl<F>(FWD(xs)...)) {
return {};
};
};
#define EMPTY()
#define DEFER(...) __VA_ARGS__ EMPTY()
#define DEFER_TWICE(...) __VA_ARGS__ DEFER(EMPTY)()
#define EXPAND(...) __VA_ARGS__
#define EVAL1(...) EXPAND(EXPAND(EXPAND(__VA_ARGS__)))
#define EVAL2(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
#define EVAL3(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
#define EVAL4(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
#define EVAL(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
#define CAT_IMPL(x, y) x##y
#define CAT(x, y) CAT_IMPL(x, y)
#define STRINGIFY_IMPL(...) #__VA_ARGS__
#define STRINGIFY(...) STRINGIFY_IMPL(__VA_ARGS__)
#define MAKE_AUTO(x) auto &&x
#define HEAD(x, ...) x
#define TAIL(x, ...) (__VA_ARGS__)
#define WHEN0(...)
#define WHEN1(...) __VA_ARGS__
#define WHEN(c) CAT_IMPL(WHEN, c)
#define NOT1 0
#define NOT0 1
#define NOT(x) CAT_IMPL(NOT, x)
#define CHECK_IMPL(x, n, ...) n
#define CHECK(...) CHECK_IMPL(__VA_ARGS__, 0)
#define PROBE(...) ~, 1
#define IS_EMPTY_IMPL(args) PROBE args
#define IS_EMPTY(args) CHECK(IS_EMPTY_IMPL(HEAD args))
#define ADD_END_SENTINEL(...) (__VA_ARGS__, ())
#define MAP(MACRO, args) \
MACRO(HEAD args) \
WHEN(NOT(IS_EMPTY(TAIL args)))(DEFER_TWICE(MAP_I)(MACRO, TAIL args))
#define MAP_I(MACRO, args) , DEFER_TWICE(MAP)(MACRO, args)
#define is_valid(args, expr) \
is_valid_f( \
[](EVAL(MAP(MAKE_AUTO, ADD_END_SENTINEL args))) -> decltype(expr) { \
return expr; \
})
struct Cat {
void meow();
};
struct Dog {
void bark();
};
int main() {
int a = 0;
int b = 1;
std::string c;
Cat cat;
Dog dog;
constexpr auto additionnable1 = is_valid((... xs), ((... + xs)));
constexpr auto additionnable2 = is_valid((x, y), x + y);
constexpr auto has_meow = is_valid((x), x.meow());
static_assert(additionnable1(a, b));
static_assert(!additionnable1(a, c));
static_assert(additionnable1(c, c));
static_assert(!additionnable2(c, a));
static_assert(has_meow(cat));
static_assert(!has_meow(dog));
}
constexpr auto foo(auto) { return 42; }
consteval auto foo(auto f) requires requires { f.value; } { return f.value; }
int main(int argc, char**) {
std::cout << foo(argc); // prints 42
constexpr struct {
int value{88};
} v;
std::cout << foo(v); // prints 88
}
注意这个requires 用法,可以在这里玩一下
代码仓库在这里 https://github.com/pigirons/sgemm_hsw
核心思想循环展开,分块计算,最大化利用ymm寄存器
有图有代码,便于理解,另外他的专栏介绍了很多linux细节,值得一看, 专栏地址直达
非常简单嗷,先装好emscripten然后确定emcc位置(在emcc目录里执行source emsdk_env.sh也行)
然后整个demo.c
double divide_numbers(double a, double b) {
return a / b;
}
double multiply_numbers(double a, double b) {
return a * b;
}
int main(int argc, char** argv) {
return -1;
}
生成js和wasm
emcc demo.c -o "myfuncs.js" -s EXPORTED_FUNCTIONS='["_multiply_numbers", "_divide_numbers"]' -s EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]' -s MODULARIZE=1 -s 'EXPORT_NAME="moduleFactory"'
生成之后,整个html来加载js
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<script type="text/javascript" src="myfuncs.js"></script>
<script>
// initialize Emscripten stack and then move on :-)
moduleFactory().then(function(Module){
var multiplyNumbers = Module.cwrap('multiply_numbers','number',['number','number']);
window.alert('3*4=' + multiplyNumbers(3,4));
var divideNumbers = Module.cwrap('divide_numbers','number',['number','number']);
window.alert('3/4=' + divideNumbers(3,4));
})
</script>
</body>
</html>
文件访问file:// 或者整个本地网页来玩,都可以,enjoy
运行时调整栈大小
#include <pthread.h>
pthread_t worker_thread;
void launch_worker(void) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 1024768);
pthread_create(&worker_thread, &attr, some_function);
}
编译期调整栈大小
指定 LDFLAGS 比如 -Wl,-z,stack-size=1024768
.也可以使用修改二进制的方法,比如 chelf / muslstack
讨论swap(v[0], v[1]);各种错误场景以及背后的故事
如果对象是临时的用emplace_back如果是局部的用push_back + std::move 最好避免push_back + copy
- Meeting C++ YT - Daniela Engert - The three secret spices of C++ Modules - Meeting C++ online 讲module的,没看。在boost没用module之前我是不会关注module的。离全面推开还有很远很远的距离
- https://github.com/cculianu/univalue 一个简单的json 库,且比nlohmann 这个要快,可以跑nlohmann bench json files 测试来比较 TODO:why?
- https://github.com/dtrugman/pfs 一个解析procfs的库