C++ 中文周刊 第19期

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

每周更新

周刊项目地址 github在线地址知乎专栏

欢迎投稿,推荐或自荐文章/软件/资源等,请提交 issue


资讯

编译器信息最新动态推荐关注hellogcc公众号

本周周报github直达

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

项目


本文永久链接

看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持! 觉得写的不错那就给点吧, 在线乞讨 微信转账