Skip to content

Releases: wanghenshui/cppweeklynews

C++ 中文周刊 第81期

23 Sep 10:12
0e4e4c9
Compare
Choose a tag to compare

reddit/hackernews/lobsters/meetingcpp/知乎等等摘抄一些c++动态

周刊项目地址在线地址知乎专栏 |腾讯云+社区

弄了个qq频道,手机qq点击进入

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

可以贴在下一期草稿里 草稿链接

2022 09 23

马上就国庆节了。节前节后这两周大概率没时间更新了。提前祝大家节日快乐。好好休息


资讯

标准委员会动态/ide/编译器信息放在这里

九月讨论汇总 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/#mailing2022-09

polymorphic_allocator<> instead of type-erasure

这个有点意思,众所周知,std::function用malloc,不能指定allocator,挺坑。如果std::function创建多了。malloc倒是成为瓶颈了。坑。
主要是加个 using allocator_type = std::pmr::polymorphic_allocator<>;

function_ref: a type-erased callable reference

这个讨论好久了。

Proxy: A Polymorphic Programming Library

这个也介绍过,是微软搞的类似folly::poly那种用户态的多态实现。

别的没啥说的。修修补补

编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-09-21 第168期

另外还有Azure CTO说c++不行了新项目转rust。c++老大说他喜新厌旧。具体大家搜一搜就好了。不贴出来了。有点八卦

问题在这里 https://www.zhihu.com/question/554750609

文章

这个分配器确实不错。差点项目里就用了。后来研究了一下发现checkpoint麻烦就放弃了。这个设计还是很有意思的

介绍防守编程的,_FORTIFY_SOURCE=3新级别,更严格,能抓到buffer overflow

被符号不匹配告警搞烦了

template <typename T>
bool has_repeated_values(const T& container) {
  for (int i = 0; i < container.size() - 1; ++i) {
    if (container[i] == container[i + 1]) return true;
  }
  return false;
}
// 修改后

std::vector vec = ...
if (!empty(vec)) {
    for (int i = 1; i < ssize(vec); ...) {
        ...
    }
}

内部帮你static_cast。快谢谢库作者

看看见识见识

介绍各个平台系统api兼容性

介绍msvc告警的。没啥说的

不太懂windows下的汇编表现

看不太懂

视频

介绍cppfront herb大哥整的新活, cpp2。看个乐

这里有个介绍 https://www.zhihu.com/question/536288519/answer/2682665038

介绍range。没啥说的

开源项目需要人手

  • asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线

新项目介绍/版本更新

  • lager 一个UI框架,类似redux

工作招聘

哎。虾皮突发变动搞的人心惶惶啊。


看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!

本文永久链接

C++ 中文周刊 第80期

16 Sep 12:29
e01cfe8
Compare
Choose a tag to compare

reddit/hackernews/lobsters/meetingcpp知乎等等摘抄一些c++动态

周刊项目地址在线地址知乎专栏 |腾讯云+社区

弄了个qq频道,手机qq点击进入

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

可以贴在下一期草稿里 草稿链接

2022 0916


资讯

标准委员会动态/ide/编译器信息放在这里

编译器信息最新动态推荐关注hellogcc公众号 2022-09-14 第167期

cppcon 2022还在进行中。视频放了几个。没看。有参与者说今年不太行。我去年还没怎么看。看视频信息量太低了。得看PPT然后找视频看。最近没啥空。周末有时间可以看看

文章

打印堆栈支持。看代码

#include <stacktrace>
#include <iostream>

int foo() {
  std::cout << std::stacktrace::current();
  return {};
}

int main() {
  return foo();
}

可算支持了

各个编译器Modules支持的状态进展介绍

标准库的std::optional是不支持T&和void的。作者说了下自己可能会用到这个场景,标准库应该加上

之前介绍过。介绍了谷歌浏览器团队在解决指针问题的一些实践。实现了很多,但是有些文档不可见。

也介绍了其他方案的实现,比如这个unowned_ptr

代码难找就没有深入研究。不过讨论还是值得一看的。我后面整理一下

介绍Sanitizer

seastar代码走读

注意co_await的阻塞语义,永远超时导致不能使用

四舍五入等于c的东西。可以看个热闹

各种容器介绍,比如folly::fbvector, boost::small_vector等等。感兴趣的可以看看

写了个工具验证gcc产出的代码对不对,具体就是验证gimple IR。我不太懂。感兴趣可以看看

office团队要用module,这是msvc团队的一些探索

介绍msvc调试的。没用过不了解,有没有懂的给讲讲

代码长这样

struct WidgetTracker : IWidgetChangeNotificationSink
{
    /* other stuff not relevant here */

    /// IWidgetChangeNotificationSink
    STDMETHODIMP OnCurrentWidgetChanged();

private:
    WRL::ComPtr<IWidget> m_currentWidget;
    std::mutex m_mutex;
};

HRESULT WidgetTracker::OnCurrentWidgetChanged()
{
    auto guard = std::lock_guard(m_mutex);
    RETURN_IF_FAILED(GetCurrentWidget(&m_currentWidget));
    return S_OK;
}

OnCurrentWidgetChanged是个回调,如果m_currentWidget变了就会被调用

问题在于OnCurrentWidgetChanged被调用这个m_mutex锁住的瞬间,m_currentWidget析构,结果又触发一次OnCurrentWidgetChanged,导致死锁

这个问题根源在于锁锁不住comptr,无法避免递归调用。

解决方法也很简单,拷贝一份对象就行了。

HRESULT WidgetTracker::OnCurrentWidgetChanged()
{
    WRL::ComPtr<IWidget> widget; // 可能别人在用它
    auto guard = std::lock_guard(m_mutex);
    RETURN_IF_FAILED(GetCurrentWidget(&widget));
    m_currentWidget.Swap(widget);
    return S_OK;
}

作者之前讨论过一段类似的代码,用的,shared_ptr, 也有相同的问题

class ThingManager
{
private:
  std::mutex things_lock_;
  std::vector<std::shared_ptr<Thing>> things_;

public:
  void AddThing(std::shared_ptr<Thing> thing)
  {
    std::lock_guard guard(things_lock_);
    things_.push_back(std::move(thing));
  }

  void RemoveThingById(int32_t id)
  {
    std::lock_guard guard(things_lock_);
    auto it = std::find_if(things_.begin(), things_.end(),
      [&](auto&& thing)
      {
        return thing->id() == id;
      });
    if (it != things_.end()) {
      things_.erase(it);
    }
  }
};

class SuperThing : Thing
{
private:
  ThingManager& manager_;
  int32_t helper_id_ = 0;

public:
  SuperThing(ThingManager& manager) :
    manager_(manager)
  {
    auto helper = std::make_shared<Thing>();
    helper_id_ = helper->id();
    manager_.AddThing(helper);
  }

  ~SuperThing()
  {
    manager_.RemoveThingById(helper_id_);
  }
};

void test(ThingManager& manager)
{
  auto s = std::make_shared<SuperThing>(manager);
  auto id = s->id();
  manager.AddThing(s);
  s = nullptr; // 1

  manager.RemoveThingById(id); // 2
}

问题是相同的,同一个锁被锁两次。如何触发?首先SuperThing会在2 这行真正的析构,1那行只会引用计数-1
RemoveThingById(id)是会锁的,内部触发了SuperThing析构,然后又调用了manager_.RemoveThingById(helper_id_);,锁了同一个锁

你可能觉得这种代码写的有问题。这是锁和shared_ptr和坑爹析构三个同时引入引发的问题,我遇不到

解决方法也很简单。让这个shared_ptr活着,因为不知道哪个外部调用会用到这个shared_ptr

void RemoveThingById(int32_t id)
{
  std::shared_ptr removed_thing; // 求求你活着
  {
    std::lock_guard guard(things_lock_);
    auto it = std::find_if(things_.begin(), things_.end(), ...);
    if (it != things_.end()) {
      removed_thing = *it;
      things_.erase(it);
    }
  }
}

引用计数指针和锁的问题。这里打个问号。要注意

oldnewthing的博客真精彩,总能遇到各种莫名其妙的bug

标准库提供了新函数来更友好的判断整数大小,不用自己写那些符号转换逻辑了

比如

template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool cmp_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept {
  static_assert(_Is_standard_integer<_Ty1> && _Is_standard_integer<_Ty2>,
   "The integer comparison functions only "
   "accept standard and extended integer types.");
  if constexpr (is_signed_v<_Ty1> == is_signed_v<_Ty2>) {
    return _Left == _Right;
  } else if constexpr (is_signed_v<_Ty2>) {
    return _Left == static_cast<make_unsigned_t<_Ty2>>(_Right) && _Right >= 0;
  } else {
    return static_cast<make_unsigned_t<_Ty1>>(_Left) == _Right && _Left >= 0;
  }
}
VPSUBUSB	z, x, y

VPMINUB		z, x, y
VPCMPEQB	w, z, x

我不太懂。不评价

用avx处理字符串中的斜杠,比如my title is \"La vie\"

通常写法

  for (...) {
    if ((*in == '\\') || (*in == '"')) {
      *out++ = '\\';
    }
    *out++ = *in;
  }

sse/avx写法

 __m512i solidus = _mm512_set1_epi8('\\');
  __m512i quote = _mm512_set1_epi8('"');
  for (; in + 32 <= finalin; in += 32) {
    __m256i input = _mm256_loadu_si256(in);
    __m512i input1 = _mm512_cvtepu8_epi16(input);
    __mmask64 is_solidus = _mm512_cmpeq_epi8_mask(input1, solidus);
    __mmask64 is_quote = _mm512_cmpeq_epi8_mask(input1, quote);
    __mmask64 is_quote_or_solidus = _kor_mask64(is_solidus, is_quote);
    __mmask64 to_keep = _kor_mask64(is_quote_or_solidus, 0xaaaaaaaaaaaaaaaa);
    __m512i shifted_input1 = _mm512_bslli_epi128(input1, 1);
    __m512i escaped =
        _mm512_mask_blend_epi8(is_quote_or_solidus, shifted_input1, solidus);
    _mm512_mask_compressstoreu_epi8(out, to_keep, escaped);
    out += _mm_popcnt_u64(_cvtmask64_u64(to_keep));
  }

给我看困了

这里有个类似的https://branchfree.org/2019/03/06/code-fragment-finding-quote-pairs-with-carry-less-multiply-pclmulqdq/

这段代码有bug,不懂这几个API的可能看不懂

bool ShuttingDown = false;

void MainThread()
{
    DWORD id;
    auto hThread = CreateThread(nullptr, 0, WorkerThread,
                                nullptr, 0, &id); // succeeds

    BlahBlahBlah(); // do useful work

    // Time to clean up. Post an APC to the worker thread
    // to tell it that it's time to go home.
    QueueUserAPC(WakeWorker, hThread, 0); // succeeds

    WaitForSingleObject(hThread, INFINITE); // hangs

    CloseHandle(hThread);
}

void CALLBACK WakeWorker(ULONG_PTR)
{
    ShuttingDown = true;
}

DWORD CALLBACK WorkerThread(void*)
{
    // Do work until shut down.
    do
    {
        // All work is posted via APCs.
        SleepEx(INFINITE, TRUE);
    } while (!ShuttingDown);

    return 0;
}

简单来说SleepEx通过QueueUserAPC来唤醒,有一种场景,QueueUserAPC唤醒了,但是CreateThread执行的慢,导致SleepEx没收到通知,从而永远死锁

怎么解决这个问题?把do while循环改成while就行了。因为这种场景已经shutdown了,不应该执行sleep

DWORD CALLBACK WorkerThread(void*)
{
    // Do work until shut down.
    while (!ShuttingDown)
    {
        // All work is posted via APCs.
        SleepEx(INFINITE, TRUE);
    } 

    return 0;
}

讲协程的。说来惭愧我还不是很懂。就不介绍了

视频

  • [C++ Weekly - E...
Read more

C++ 中文周刊 第79期

09 Sep 07:09
Compare
Choose a tag to compare

reddit/hackernews/lobsters/purecpp知乎等等摘抄一些c++动态

周刊项目地址在线地址知乎专栏 |腾讯云+社区

弄了个qq频道,手机qq点击进入

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

可以贴在下一期草稿里 草稿链接

2022 0908 提前发了。周五有事

资讯

标准委员会动态/ide/编译器信息放在这里

llvm 15发布了。c++20支持等等一大堆修改

lld 15 ELF changes

编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-09-07 第166期

文章

要注意协程被线程切换影响

c++23详细总结

c++20应用协程举例

std::function的分析

seastar的一些代码走读。可以看看

其实就是编译期检测接口的能力

一组协程教程

#include <ranges>

template <auto Begin, auto End, auto List>
auto slice = List
           | std::ranges::views::drop(Begin)
           | std::ranges::views::take(End);

static_assert(
  slice<1_c, 2_c, boost::mp::list<int, double, float>()>
  ==
                  boost::mp::list<double, float>());

typelist实现更简单了。恐怖

optinal的move并不会真正的move T, 让T为无效value

template <typename T>
void test(T v)
{
  optional<T> o = v;
  assert (o);     // o contains a value
  optional<T> p = std::move(o);
  assert (o);     // o still contains a value!
}

完全取决于T的move,optional会保留T的壳子。

比如unique_ptr

int * p = new int(1);
 
optional<unique_ptr<int>> op = unique_ptr<int>(p);
assert (op);
assert (op->get() == p);
 
optional<unique_ptr<int>> o2 = std::move(op);
assert (op);                   // still contains a value
assert (op->get() == nullptr); // the value is moved from
assert (o2);
assert (o2->get() == p);

unique_ptr内部会搬走,但本身是还在optional里的。这样实现更快,对于trival类型,这样优化的可以直接memcpy,更高效一些
大概实现成这个样子

template <typename Trivial>
class optional<Trivial>
{
  bool     _is_initialized;
  Trivial  _value;
 
  optional() : _is_initialized(false) {}
  // use defaulted copy and move 
};
// Second argument is a pointer to the type of std::fclose, we could also have
// written it out explicitly as std::unique_ptr<FILE, int (*)(FILE*)>.
using FilePtr = std::unique_ptr<FILE, decltype(std::fclose) *>;

// Instantiate the FILE* with the destructor we want.
FilePtr file(std::fopen(filename, "rbe"), std::fclose);

// Do stuff with the file
std::fread(buf_.data(), 1, buf_.size(), file.get());

比写个deferGuard能更干净些

using XXH3StatePtr = std::unique_ptr<XXH3_state_t, decltype(XX3_freeState) *>;
XXH3StatePtr state(XXH3_createState(), XXh3_freeState);

但这种写法的问题在于,需要判定创建失败/指针是否有效

一个简单的函数

[[nodiscard]] auto say_a_to(
    std::string_view what, std::string_view name) -> std::string {
  return std::string{what} + ", " + std::string{name} + "!";
}

say_a_to("Hi", "Kate"); // -> "Hi, Kate!"

struct {
  [[nodiscard]] auto operator()(
      std::string_view what, std::string_view name) const -> std::string {
    return std::string{what} + ", " + std::string{name} + "!";
  }
} say_b_to;

say_b_to("Hello", "Tony"); // -> "Hello, Tony!"

没啥新奇的,但是c++23支持多维数组了,所以说operator[] 也算是一种函数了

比如

struct {
  [[nodiscard]] auto operator[](
      std::string_view what, std::string_view name) const -> std::string {
    return std::string{what} + ", " + std::string{name} + "!";
  }
} say_d_to;

say_d_to["Goodbye", "Tony"]; // -> "Goodbye, Tony!"
struct {
  template <std::integral ...Ts>
  [[nodiscard]] auto operator[](Ts... ts) const noexcept {
    return (0 + ... + ts);
  }
} sum;
const auto s1 = sum[1, 2, 3]; // 6
const auto s2 = sum[];        // 0

我只能说看个乐,别这么写求求了

视频

#include <iostream>
#include <ranges>
#include <string_view>

int main() {

  // this is lazily evaluated
  auto strings = std::string_view{"Hello C++ 20"} | std::views::split(' ');

  // the result is a range of ranges
  
  for (const auto &ref : strings) {
    // C++ 20
    std::cout << '\n' << std::string_view{ref.begin(), ref.end()};
    // C++ 23
    std::cout << '\n' << std::string_view{ref};
  }
}

开源项目需要人手

  • asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线

工作招聘

寒冬了

华为出新手机了,但我不买,因为想把寒冬传给它

看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!

本文永久链接

C++ 中文周刊 第78期

02 Sep 13:28
d25cee6
Compare
Choose a tag to compare

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

周刊项目地址在线地址知乎专栏 |腾讯云+社区

弄了个qq频道,手机qq点击进入

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

可以贴在下一期草稿里 草稿链接

2020 09 02


资讯

标准委员会动态/ide/编译器信息放在这里

编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-08-31 第165期

文章

尽量让move 构造函数 noexcept, 不然用vector可能有问题,多copy

比如这个

struct Instrument {
    int n_;
    std::string s_;

    Instrument(const Instrument&) = default;

    // WRONG!!
    Instrument(Instrument&& rhs)
        : n_(std::exchange(rhs.n_, 0)),
          s_(std::move(s_))
        {}

    // RIGHT!!
    Instrument(Instrument&& rhs) noexcept
        : n_(std::exchange(rhs.n_, 0)),
          s_(std::move(s_))
        {}
};

如果不是noexcept,vector的move判定内部的T不是is_nothrow_move_constructible, 那就构造复制一份,所以多了个拷贝。也就是博主说的vector pessimization问题

vector本身的搬迁move的多余动作,如果能nothrow,move就更简单

free没有size看上去是个巧妙的设计,实际上隐含了挺多脏活

协程背后都做了啥

有点意思

struct foo {
   [[nodiscard]] foo(auto& resource) {}
};

struct [[nodiscard]] bar {};

auto fn() -> bar;

[[nodiscard]] auto fn2() -> bool;

int main(int, char** argv){
    foo{argv}; // ignoring temp created by [[nodiscard]]
    fn();      // ignoring return value with [[nodiscard]]
    fn2();     // ignoring return value with [[nodiscard]]
}

老文,科普一下概念。

参数不是constexpr

consteval auto square(int x) -> int { return x * x; }

constexpr auto twice_square(int x) -> int { return square(x); }

编译不过。作者展示了一下编译期计算。哎又回去了。constexpr还是不够const

看个乐

介绍这几个flag

-march=native肯定接触过吧

茴香豆的茴的20种写法

为什么大哥解bug这么熟练

视频

static constexpr 和 inline constexpr区别。inline constexpr能合并文件重复的数据,是文件级别,static是函数级别,并不能合并代码段

聪明的你想到了static inline constexpr。这个效果就是static constexpr。static限制了范围

开源项目需要人手

  • asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线

工作招聘

寒冬了


看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!

本文永久链接

C++ 中文周刊 第77期

26 Aug 11:50
67f934a
Compare
Choose a tag to compare

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

周刊项目地址在线地址知乎专栏 |腾讯云+社区

弄了个qq频道,手机qq点击进入

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

可以贴在下一期草稿里 链接

2022 08 26

准备做视频,目前有代码走读/benchmark俩主题,大家还有啥意见可以供稿一下。下一期视频准备先来个userver代码走读。我先准备准备材料


资讯

标准委员会动态/ide/编译器信息放在这里

标准委员会八月邮件 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/#mailing2022-08

编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-08-24 第164期

文章

namespace detail {
template <bool> struct conditional;
template <> struct conditional<false> {
  template <class, class T> using fn = T;
};
template <> struct conditional<true> {
  template <class T, class> using fn = T;
};
} // namespace detail

template <bool B, typename T, typename F>
using conditional_t = typename detail::conditional<B>::template fn<T, F>;

说实话,没看懂

关于协程的封装探索,挺有意思的

看不懂

GCC整体介绍

看个乐

fmt对输出有严格限制

介绍他自己写的静态检查器 https://github.com/GregUtas/robust-services-core

main函数执行前都干了啥,填充入参之类的

#include <iostream>
#include <string>
#include <stdlib.h>

std::string message;

extern "C" {
void __asan_on_error() {
  std::cout << "You caused an error: " << message << std::endl;
}
}


int main() {
  int array[8];
  for(int k = 0;; k++) {
    message = std::string("access at ") + std::to_string(k);
    array[k] = 0;
  }
  return EXIT_SUCCESS;
}

不过不太实用

memcmp比较出错。qemu这种牛逼软件也会有这种问题啊

int arr[10000];    // 一个已有的数组
mdspan mdarr{arr, i, j, k};  // 把已有的数组 arr 视作 i×j×k 的多维数组
int value = mdarr[x, y, z];  // 访问多维数组的元素
mdarr[x, y, z] = 42;         // 向元素赋值

简而言之就是这几行。现在你已经学会了

视频

-ftime-trace 生成编译的时间json结果,可以用chrome://tracing/ 浏览器来加载查看。可以自己试一试

觉得麻烦想快速验证的,这里有个build bench https://build-bench.com/b/zLopSp4Yj5XaijZSuwqiYvA2PNU

开源项目需要人手

  • asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线

新项目介绍/版本更新

工作招聘

突然寒冬卧槽了,任正非你这嘴开过光吧


看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!

本文永久链接

C++ 中文周刊 第76期

19 Aug 12:29
Compare
Choose a tag to compare

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

周刊项目地址在线地址知乎专栏 |腾讯云+社区

弄了个qq频道,手机qq点击进入

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

可以贴在下一期草稿里 https://github.com/wanghenshui/cppweeklynews/blob/dev/posts/077.md

2022 08 19

解不出bug要被开了。有没有工作岗位推荐的


资讯

标准委员会动态/ide/编译器信息放在这里

编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-08-17 第163期

文章

类似folly::Poly

std::expected<std::vector<int>, Status> ReadData()
{
   if (!HasAcccess())
      return std::unexpected<Status> { Status::AccessDenied };
   if (OpenConnection() != 0)
      return std::unexpected<Status> {Status::DataSourceError};
   if (Fetch() != 0)
      return std::unexpected<Status> {Status::DataError};
   std::vector<int> data;
   data.push_back(42);
   return data;
}

相当于StatusWith<T>这种组件

void report_error();
[[gnu::cold]] void report_error_cold();
void logic();

/*
cold(bool):
        test    edi, edi
        jne     .LBB0_1
        jmp     logic()
.LBB0_1:
        jmp     report_error_cold()
*/
auto cold(bool error) {
    if (error) {
        report_error_cold();
        return;
    }

    logic();
}

/*
normal(bool):
        test    edi, edi
        je      .LBB1_2
        jmp     report_error()
.LBB1_2:
        jmp     logic()
*/
auto normal(bool error) {
    if (error) {
        report_error();
        return;
    }

    logic();
}

/*
unlikely(bool):
        test    edi, edi
        jne     .LBB2_1
        jmp     logic()
.LBB2_1:
        jmp     report_error()
*/
auto unlikely(bool error) {
    if (error) [[unlikely]] {
        report_error();
        return;
    }

    logic();
}

对代码优化有点帮助。之前也介绍过

对比了一下各种atomic 锁之类的差异

看个乐

这个优化了解一下

视频

// #embed 支持
//#embed </path/to/file.txt>

//constexpr 部分支持
// not allowed in c23 :(
//constexpr int get_value() {
//  return 42;
//}
// allowed in c23!
constexpr int universe_and_everything = 42;

// [[attributes]]支持
[[nodiscard]] int get_value();
// deprecated, fallthrough, maybe_unused, nodiscard, noreturn

// 未命名参数
int do_work(int x, int)
{
  return x * 23;
}

// 类型枚举
enum MyEnum : char {
  x,
  y
};

// #6 __has_include
#if __has_include("somefile")
#include("somefile");
#endif

开源项目需要人手

  • asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线

新项目介绍/版本更新

  • bloaty 查看代码的膨胀程度
  • passgen 根据指定正则生成密码
  • async_simple 协程库,阿里的,有demo。不过是部分开源
  • natalie c++写的ruby
  • jank c++写的Clojure

工作招聘

解不出bug要被开了


看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!

本文永久链接

C++ 中文周刊 第74期 && 75期

12 Aug 11:32
Compare
Choose a tag to compare

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

周刊项目地址在线地址知乎专栏 |腾讯云+社区

弄了个qq频道,手机qq点击进入

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

74忘记发了。74 75 合着发吧


资讯

标准委员会动态/ide/编译器信息放在这里

编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-08-03 第161期

文章

c++的bind和网络库的bind符号冲突了。很搞笑。不过在linux环境下没有这个问题
我之前在windows平台遇到过log日志接口和cmath的log函数有符号冲突。msvc这个方面做的不是很好

/*
divide_by_32_no_assume(int):
        lea     eax, [rdi + 31]
        test    edi, edi
        cmovns  eax, edi
        sar     eax, 5
        ret
*/
auto divide_by_32_no_assume(int x) {
    return x / 32;
}


/*
divide_by_32_assume(int):
        mov     eax, edi
        shr     eax, 5
        ret
*/
auto divide_by_32_assume(int x) {
    __builtin_assume(x >= 0);
    return x / 32;
}

这个之前提到过,有个经典的fast-math开关优化。那个力度比较大。这里你可以自主控制,力度更精细一些

同一个代码段 c和c++有很大区别。主要是逗号表达式,左值右值,位域,类型转换,类型大小,空类型,匿名结构体等等。感兴趣的可以看看。

介绍TSAN的原理

介绍内核内存分配策略

用c++实现structopt, 看个乐

没看明白

一个bug

template<class It>
bool is_palindrome(It first, It last) {
    while (first != last) {
        --last;
        if (first == last) break;
        if (*first != *last) {
            return false;
        }
        ++first;
    }
    return true;
}

很自然的,可以改写成

template<class It>
bool is_palindrome(It first, It last) {
    return std::equal(
        first, last,
        std::reverse_iterator(last),
        std::reverse_iterator(first)
    );
}

这里没用make_reverse_iterator,用的CTAD自动推导。但是这个推导可能不是我们预想的那样

std::string s = "foo";
assert(!is_palindrome(s.begin(), s.end()));
assert(is_palindrome(s.begin()+1, s.end()));
assert(!is_palindrome(s.rbegin(), s.rend()));
assert(is_palindrome(s.rbegin(), s.rend()-1));  // Fails! Oof!

最后两个例子,已经是reverse的iterator, CTAD什么都不做,而不是推导成 reverse_iterator<iterator>这种东西,所以报错了

尽量别用CTAD。降低入门门槛但是引入了背景,不熟就掉坑

基础知识。值得看看

static_assert(typeid([]{}) != typeid([]{}));

template<auto = []{}>
struct foo{};

foo f1, f2;
static_assert(typeid(f1) != typeid(f2));

没什么卵用的知识,也是一个坑

利用concept和constexpr代替enable if 代码不列举了

int main()
{
    constexpr auto factorial23 = [](this auto&& self, int n) {
		if (n <= 1)
			return 1;
		return n * self(n - 1);
	};
    static_assert(factorial23(5) == 120);
}

递归+编译期 lambda,玩的花

分析bug挺有意思

老生常谈了,可读性问题,别用bool做多个参数,不然分不清啥是啥

简单压测,QT的信号槽比虚函数观察者模式并不快。看个乐

仓库在这里https://github.com/rnburn/rules_cc_module

总算支持了

一个课程,可以看看

值得一看,拓展思路

又是SIMD。可以看看

gdb调试。值得一看

视频

代码在这里https://compiler-explorer.com/z/nbGGdMM4b

开源项目需要人手

  • asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线

新项目介绍/版本更新

工作招聘


看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!

本文永久链接

C++ 中文周刊 第73期

29 Jul 12:26
Compare
Choose a tag to compare

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

周刊项目地址在线地址知乎专栏 |腾讯云+社区

弄了个qq频道,手机qq点击进入

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

2022 07 29


资讯

标准委员会动态/ide/编译器信息放在这里

编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-07-27 第160期

文章

手把手教你写错误处理的代码

值得一看

使用folly遇到的问题以及解决。看个乐

了解一下

概念复习

概念复习

压测代码在这里https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/tree/master/2020/09/10

速度对比 strtod 270 MB/s from_chars 1 GB/s 用哪个不用我多说了吧

windows我不懂,不过还可以这么操作的??

开源项目需要人手

  • asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线

新项目介绍/版本更新

  • STL MSVC STL组老大自己实现的刚进c++23的import std; 感谢@c8ef 投稿
  • lazyfs 一个fake fs实现
  • listdb 论文开源代码。基于pmem,生成比直接用pmdk的rocksdb快 今天突然得知pmem 被英特尔砍了。悲
  • jsonpp 一个json库

工作招聘

有没有需要看大门的


看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!

本文永久链接

C++ 中文周刊 第72期

27 Jul 06:16
Compare
Choose a tag to compare

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

周刊项目地址在线地址知乎专栏 |腾讯云+社区

弄了个qq频道,手机qq点击进入

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

2022 0726 最近有点忙


资讯

标准委员会动态/ide/编译器信息放在这里
七月邮件汇总

编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-07-20 第159期

文章

讲完美哈希表的。这个知识好像没怎么普及开,这里推荐一下

一个思路,禁止各种make,只能从静态函数构造

template<typename T>
struct require_make_shared :
    public std::enable_shared_from_this<T>
{
protected:
    struct use_the_create_method {
        explicit use_the_create_method() = default;
    };

public:
    template<typename...Args>
    static auto create(Args&&... args)
    {
        return std::make_shared<T>
            (use_the_create_method{},
             std::forward<Args>(args)...);
    }

    // Deny copy construction
    require_make_shared(require_make_shared const&) = delete;
};

class Widget : public require_make_shared<Widget>
{
public:
    Widget(use_the_create_method);
    Widget(use_the_create_method, int);
    Widget(use_the_create_method, int, int);
};

void test()
{
    auto v1 = Widget::create(); // okay
    auto v2 = std::make_shared<Widget>(); // nope
    auto v3 = std::make_unique<Widget>(); // nope
    Widget v4; // nope
}
std::string s{"there is a needle in the haystack"};
std::string_view sv{"acdef"};

if (s.contains("needle")) { // 总算有这个api了
    std::cout << "we found a needle in: " << std::quoted(s) << '\n';
}

if (!sv.contains('b')) {
    std::cout << "we did not find a 'b' in: " << std::quoted(sv) << '\n';
}

std::string s(nullptr); //不会挂了

basic_string::resize_and_overwrite() 可以省一个写,用不上的可以先用gcc内置函数

std::string s { "Food: " };
s.resize_and_overwrite(10, [](char* buf, int n) {
    return std::find(buf, buf + n, ':') - buf;
});
std::cout << "2. " << std::quoted(s) << '\n';

c23支持embed了,c++23还不支持std::embed。服了

介绍一下embed,看代码你就懂了

#include <assert.h>

int main (int, char*[]) {
	static const char sound_signature[] = {
#embed <sdk/jump.wav>
	};
	static_assert((sizeof(sound_signature) / sizeof(*sound_signature)) >= 4,
		"There should be at least 4 elements in this array.");

	// verify PCM WAV resource signature (at run-time)
	assert(sound_signature[0] == 'R');
	assert(sound_signature[1] == 'I');
	assert(sound_signature[2] == 'F');
	assert(sound_signature[3] == 'F');

	return 0;
}

定制formatter,代码不贴了

auto foo(auto&&);

int main() {
    int i{};
    const int c{};

    foo(42);       // int
    foo(i);        // int&
    foo(int{i});   // int
    foo(auto{i});  // int
    foo(auto(42)); // int
    foo(c);        // const int&
    foo(int{c});   // int
    foo(auto(c));  // int
}

这个也讲过很多次了。有些场景是需要copy语义的,否则莫名其妙出现了改动,解决办法就是让他退化,拿到copy

这个例子也说过很多次了

#include <iostream>

template<class T> 
constexpr std::decay_t<T>
decay_copy(T&& v)
    noexcept(std::is_nothrow_convertible_v<T, std::decay_t<T>>)           // exposition only
{
     return std::forward<T>(v);
}

int main() {
  std::vector<int> v1{1, 2, 1, 1, 1};
  auto v2 = v1;
  v1.erase(
      std::remove(begin(v1), end(v1), *std::max_element(begin(v1), end(v1))),
      v1.end());
  v2.erase(std::remove(
               begin(v2), end(v2),
               decay_copy(*std::max_element(begin(v2), end(v2)))),
           v2.end());
  std::cout << "v1.size()=" << v1.size() << std::endl 
            << "v2.size()=" << v2.size()
            << std::endl;
  return 0;
}

p2162继承variant各个编译器已经支持了。作者展示了一种优雅的用法

#include <cstdint>
#include <iostream>

using namespace std;

struct Request {
  static constexpr uint8_t id_num {1};
  uint8_t req_val;

  void encode(ostream& os) const {
    os.put(req_val);
  }

  void decode(istream& is) {
    req_val = is.get();
  }
};

struct Affirmative {
  static constexpr uint8_t id_num {2};
  uint8_t resp_val;

  void encode(ostream& os) const {
    os.put(resp_val);
  }

  void decode(istream& is) {
    resp_val = is.get();
  }
};

struct Failure {
  static constexpr uint8_t id_num {3};
  uint8_t resp_val;

  void encode(ostream& os) const {
    os.put(resp_val);
  }

  void decode(istream& is) {
    resp_val = is.get();
  }
};

#include <variant>
#include <exception>

struct Packet : variant<Request, Affirmative, Failure> {
  using variant::variant;

  Packet(uint8_t id) : variant {from_id(id)} {}

  Packet(istream& is) {
    decode(is);
  }

  void encode(ostream& os) const {
    visit([&](const auto& inner){
      os.put(inner.id_num);
      inner.encode(os);
    }, *this);
  }

  void decode(istream& is) {
    *this = from_id(is.get());
    visit([&](auto& inner){ inner.decode(is); }, *this);
  }

private:
  static Packet from_id(uint8_t id) {
    switch(id) {
      case Request::id_num:
        return Request {};
      case Affirmative::id_num:
        return Affirmative {};
      case Failure::id_num:
        return Failure {};
    }
    throw std::runtime_error {"Invalid Packet Id!"};
  }
};

#include <concepts>
#include <sstream>

#include <fmt/format.h>
using fmt::print;

int main(void) {
  Packet p {Request {.req_val {5}}};
  stringstream buf;

  p.encode(buf);

  Packet decoded {buf};
  visit([](const auto& inner){
    using T = decltype(auto(inner));
    if constexpr(same_as<T, Request>)
      print("I am a Request with a val of: {}", inner.req_val);
    else if constexpr(same_as<T, Affirmative>)
      print("I am an Affirmative with a val of: {}", inner.resp_val);
    else if constexpr(same_as<T, Failure>)
      print("I am a Failure with a val of: {}", inner.resp_val);
  }, decoded);
}

这种写法确实挺爽的,有点猥琐的模式匹配那个味了,https://godbolt.org/z/rqYeY5r1f

作者也展示了用concept达到类似的效果

#include <concepts>

struct Stranger {};

using Person = variant<Alice, Bob, Stranger>;

template <typename T>
concept IsNamed = requires(T p) {
  { p.name() } -> convertible_to<string_view>;
};

void print_name(Person& p) {
  visit([](auto& inner) {
    if constexpr(IsNamed<decltype(inner)>)
      print("Name: {}\n", inner.name());
    else
      print("This is a stranger!\n");
  }, p);
}

也不是不行,就是concept一般人比较不好接受

讲裁剪二进制的。

视频

通过函数make_lambda返回一个lambda,然后推导这个lambda的类型,就可以放到vector里了。直接用lambda不行,类型信息是匿名的,无法使用。
或者用std::function不就行了?

开源项目需要人手

  • asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线

新项目介绍/版本更新

说实话格局低了。自己开新坑不如隔壁meta推出新IR修缮
另外下一个c++不是rust么,都这么多年了,为啥会选你carbon,除非像go一样硬推

工作招聘

有没有需要招扫地僧式保洁的。我会拖地


看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!

本文永久链接

C++ 中文周刊 第71

15 Jul 13:32
Compare
Choose a tag to compare

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

周刊项目地址在线地址知乎专栏 |腾讯云+社区

弄了个qq频道,手机qq点击进入

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

2022 07 15


资讯

CPPcon 2022要开始了。2021我还没有看完

标准委员会动态/ide/编译器信息放在这里

编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-07-13 第158期

文章

值得一看

值得一看

了解一下asio的背景

上面这四篇都是purecpp公众号的。大家也可以去公众号看看

感兴趣的看下吧。数学和图形学?看不懂

手把手教你写代码,考虑各种场景

介绍msvc特性

arm的特性。现在arm的机器越来越多了。省钱
代码长这样。有兴趣的可以看看,我看不懂

void remove_negatives(const int32_t *input, int64_t count, int32_t *output) {
  int64_t j = 0;
  const int32_t* endPtr = input + count;
  const uint64_t vl_u32 = svcntw();

  svbool_t all_mask = svptrue_b32();
  while(input <= endPtr - (4*vl_u32))
  {
      svint32_t in0 = svld1_s32(all_mask, input + 0*vl_u32);
      svint32_t in1 = svld1_s32(all_mask, input + 1*vl_u32);
      svint32_t in2 = svld1_s32(all_mask, input + 2*vl_u32);
      svint32_t in3 = svld1_s32(all_mask, input + 3*vl_u32);

      svbool_t pos0 = svcmpge_n_s32(all_mask, in0, 0);
      svbool_t pos1 = svcmpge_n_s32(all_mask, in1, 0);
      svbool_t pos2 = svcmpge_n_s32(all_mask, in2, 0);
      svbool_t pos3 = svcmpge_n_s32(all_mask, in3, 0);

      in0 = svcompact_s32(pos0, in0);
      in1 = svcompact_s32(pos1, in1);
      in2 = svcompact_s32(pos2, in2);
      in3 = svcompact_s32(pos3, in3);

      svst1_s32(all_mask, output + j, in0);
      j += svcntp_b32(all_mask, pos0);
      svst1_s32(all_mask, output + j, in1);
      j += svcntp_b32(all_mask, pos1);
      svst1_s32(all_mask, output + j, in2);
      j += svcntp_b32(all_mask, pos2);
      svst1_s32(all_mask, output + j, in3);
      j += svcntp_b32(all_mask, pos3);

      input += 4*vl_u32;
  }

  int64_t i = 0;
  count = endPtr - input;

  svbool_t while_mask = svwhilelt_b32(i, count);
  do {
    svint32_t in = svld1_s32(while_mask, input + i);
    svbool_t positive = svcmpge_n_s32(while_mask, in, 0);
    svint32_t in_positive = svcompact_s32(positive, in);
    svst1_s32(while_mask, output + j, in_positive);
    i += svcntw();
    j += svcntp_b32(while_mask, positive);
    while_mask = svwhilelt_b32(i, count);
  } while (svptest_any(svptrue_b32(), while_mask));
}

目测协程还是不太成熟,clang的文档可以看看

讲folly实现的。值得一看

讲位运算的。不如看hacker‘s delight

视频

抽象程度 std::function callable,是个能存的对象,能存lambda
lambda只是一个能call的对象。右值。比函数对象能灵活点,匿名函数对象
函数指针也是个能存的,但是比std::function残废,不能保存有状态的lambda,比如有捕获的lambda

手把手教你写any

讲的整型约束。这个在cppcoin 2021上讲过。听不动。很困

开源项目需要人手

  • asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线

新项目介绍/版本更新

工作招聘

有没有小卖铺缺收银员


看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!

本文永久链接