C++ 中文周刊 第127期

2024-07-30 14:21:08 浏览数 (1)

资讯

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

编译器信息最新动态推荐关注hellogcc公众号 本周更新 2023-08-16 第215期 [1]

boost 1.8.3发布,最后一个支持c 03的版本

https://www.boost.org/users/history/version_1_83_0.html

重点发布就是boost::concurrent_flat_map

代码语言:javascript复制
Unordered:
Major update.
Added boost::concurrent_flat_map, a fast, thread-safe hashmap based on open addressing.
Sped up iteration of open-addressing containers.
In open-addressing containers, erase(iterator), which previously returned nothing, now returns a proxy object convertible to an iterator to the next element. This enables the typical it = c.erase(it) idiom without incurring any performance penalty when the returned proxy is not used.

文章

Did you know that C 26 std.format added formatting pointers ability [2]
代码语言:javascript复制
int main() {
    auto i = 42;
    std::cout << std::format("{:#018X}", reinterpret_cast<uintptr_t>(&i)); // prints 0X00007FFD9D71776C
}

有点用,但也不是很多

模板元编程的精妙之--2/16进制字面量转换为编译期字符串 [3]
代码语言:javascript复制
  asio::const_buffer b5 = 0xaB_buf;
  ASIO_CHECK(b5.size() == 1);
  ASIO_CHECK(memcmp(b5.data(), "xab", 1) == 0);

  asio::const_buffer b6 = 0xABcd_buf;
  ASIO_CHECK(b6.size() == 2);
  ASIO_CHECK(memcmp(b6.data(), "xabxcd", 2) == 0);

  asio::const_buffer b7 = 0x01ab01cd01ef01ba01dc01fe_buf;
  ASIO_CHECK(b7.size() == 12);
  ASIO_CHECK(memcmp(b7.data(),
        "x01xabx01xcdx01xefx01xbax01xdcx01xfe", 12) == 0);

编译期hex转字符串。很妙

代码在这里 https://github.com/chriskohlhoff/asio/blob/master/asio/include/asio/buffer.hpp#L2743

Inside STL: Smart pointers[4]

shared_ptr有额外的计数信息, 大概这样

代码语言:javascript复制
struct control_block {
    virtual void Dispose() = 0;
    virtual void Delete() = 0;
    std::atomic<unsigned long> shareds;
    std::atomic<unsigned long> weaks;
};
template<typename T>
struct shared_ptr {
    T* object;
    control_block* control;
};

template<typename T>
struct weak_ptr {
    T* object;
    control_block* control;
};

unique_ptr比较简单,就是指针 deleter,然后空基类优化(compressed_pair)

Inside STL: The shared_ptr constructor vs make_shared[5]

讲智能指针的内存布局

shared_ptr是有额外的信息的,这部分信息需要一个分配

代码语言:javascript复制
auto p = std::shared_ptr<S>(new S());
auto p = std::make_shared<S>();

这两种构造,第一种,由于是接管,S的内存和shared_ptr内部信息不是连续的,这对局部性缓存是不友好的

Inside STL: The shared_ptr constructor and enable_shared_from_this[6]

enable_shared_from_this怎么实现的?大概思路就是weak_ptr

代码语言:javascript复制
template<typename T>
struct enable_shared_from_this {
    using esft_detector = enable_shared_from_this;
    std::weak_ptr<T> weak_this;

    std::weak_ptr<T> weak_from_this()
    { return weak_this; }

    std::shared_ptr<T> shared_from_this()
    { return weak_this.lock(); }

};

weak_this由谁来赋值?肯定是shared_ptr拉

代码语言:javascript复制
template<typename T, typename D>
struct shared_ptr {
    shared_ptr(T* ptr)
    {
        ... do the usual stuff ...

        /* Here comes enable_shared_from_this magic */
        if constexpr (supports_esft<T>::value) {
            using detector = T::esft_detector;
            ptr->detector::weak_this = *this;
        }
    }

    ... other constructors and stuff ...
};

只要enable_shared_from_this实现 esft_detector就行了,类似这样

代码语言:javascript复制
template<typename T, typename = void>
struct supports_esft : std::false_type {};

template<typename T>
struct inline bool supports_esft<T,
    std::void_t<typename T::esft_detector>>
    : std::true_type {};

这样继承的类都有特化的shared_ptr构造

C 23: mdspan[7]

编译器还没加上这个能力,可以用这个体验 https://github.com/kokkos/mdspan,在线 https://godbolt.org/z/Mxa7cej1a

之前也讲过很多次了,直接贴代码吧

代码语言:javascript复制
std::array numbers {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
stdex::mdspan<int, stdex::extents<int, 2, 5>, stdex::layout_right> mdspanOfNumbers {numbers.data()};
for (size_t rowIndex=0; rowIndex < mdspanOfNumbers.extent(0);   rowIndex) {
    for (size_t columnIndex=0; columnIndex < mdspanOfNumbers.extent(1);   columnIndex) {
        std::cout << mdspanOfNumbers[rowIndex, columnIndex] << ' ';
    }
    std::cout << 'n';
}

/*
1 2 3 4 5 
6 7 8 9 10 
*/

std::array numbers {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
stdex::mdspan<int, stdex::extents<int, 2, 5>, stdex::layout_left> mdspanOfNumbers {numbers.data()};
for (size_t columnIndex=0; columnIndex < mdspanOfNumbers.extent(0);   columnIndex) {
    for (size_t rowIndex=0; rowIndex < mdspanOfNumbers.extent(1);   rowIndex) {
        std::cout << mdspanOfNumbers[columnIndex, rowIndex] << ' ';
    }
    std::cout << 'n';
}
/*
1 3 5 7 9 
2 4 6 8 10 
*/
Transcoding UTF-8 strings to Latin 1 strings at 18 GB/s using AVX-512[8]

SIMD时间

常规

代码语言:javascript复制
uint8_t leading_byte = data[pos]; // leading byte
if (leading_byte < 0b10000000) {
  *latin_output   = leading_byte;
  pos  ;
} else if ((leading_byte & 0b11100000) == 0b11000000) {
  *latin_output   = (leading_byte & 1) << 6 | (data[pos   1]);
  pos  = 2;
}

simd

代码语言:javascript复制
__m512i input = _mm512_loadu_si512((__m512i *)(buf   pos));
__mmask64 leading = _mm512_cmpge_epu8_mask(input, _mm512_set1_epi8(-64));
__mmask64 bit6 = _mm512_mask_test_epi8_mask(leading, input, _mm512_set1_epi8(1));
input = _mm512_mask_sub_epi8(input, (bit6<<1) | next_bit6, input, _mm512_set1_epi8(-64));
next_bit6 = bit6 >> 63;
__mmask64 retain = ~leading;
__m512i output = _mm512_maskz_compress_epi8(retain, input);
int64_t written_out = _popcnt64(retain);
__mmask64 store_mask = (1ULL << written_out) - 1;
_mm512_mask_storeu_epi8((__m512i *)latin_output, store_mask, output);

完整代码 https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/tree/master/2023/08/11

Some C 20 ranges aren’t const-iterable[9]

range的坑,没有完全零开销,需要拷贝

Writing custom C 20 coroutine systems[10]

手把手教你写协程

Parameter Passing in Flux versus Ranges[11]

他也写了个range库 flux,对比了一下和range的差异,优缺点

How to convert an enum to string in C [12]

推荐使用magic_enum

视频

CppNow基本上一周出几个视频,列个有意思的

The New C Library: Strong Library Foundation for Future Projects - Jonathan Müller & Arno Schödl [13]

ppt在这里 https://www.jonathanmueller.dev/talk/think-cell-library/

代码在这里 https://github.com/think-cell/think-cell-library

非常通用的组件介绍

比如std::exchange

代码语言:javascript复制
template <typename T>
class my_smart_ptr {
    T* _ptr;
  public:
    my_smart_ptr(my_smart_ptr&& other) noexcept
    : _ptr(other._ptr) {
        other._ptr = nullptr;
    }
};

用上exchange

代码语言:javascript复制
template <typename T>
class my_smart_ptr {
    T* _ptr;
  public:
    my_smart_ptr(my_smart_ptr&& other) noexcept
    : _ptr(std::exchange(other._ptr, nullptr))
    {}
};

这种语义是upsert,不只指针,其他value也可以这样优化,代码干净

所以实现了tc::change

代码语言:javascript复制
void tc::optional<T>::reset() {
    if (_has_value) {
        _has_value = false;
        value().~T();
    }
}

使用tc::change

代码语言:javascript复制
void tc::optional<T>::reset() {
    if (tc::change(_has_value, false)) {
        value().~T();
    }
}

为啥为了省一个if这么麻烦?,举个例子,异常 重入

代码语言:javascript复制
void foo1() {
    …
    if (dirty) {
        clean();
        dirty = false;
    }
    …
}

void foo2() {
    …
    if (tc::change(dirty, false)) {
        try {
            clean();
        } catch (...) {
            dirty = true;
            throw;
        }
    }
    …
}

foo2比foo1更健壮点,避免了同时clean的场景

假如多个线程都在clean,而clean时间较长,dirty更新不及时,就更新了多次

foo2就避免了这种情况

还有一些range string的就不列了,感兴趣的可以看看

开源项目需要人手

  • • asteria[14] 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • • Unilang[15] deepin的一个通用编程语言,点子有点意思,也缺人,感兴趣的可以github讨论区或者deepin论坛看一看。这里也挂着长期推荐了
  • • gcc-mcf[16] 懂的都懂

工作招聘

有没有数据库相关的工作推荐我一下,我要失业了快(能远程更好)

本文永久链接[17]

如果有疑问评论最好在上面链接到评论区里评论,这样方便搜索,微信公众号有点封闭/知乎吞评论

引用链接

[1] 编译器信息最新动态推荐关注hellogcc公众号 本周更新 2023-08-16 第215期 : https://github.com/hellogcc/osdt-weekly/blob/master/weekly-2023/2023-01-04.md [2] Did you know that C 26 std.format added formatting pointers ability : https://github.com/tip-of-the-week/cpp/blob/master/tips/343.md [3] 模板元编程的精妙之--2/16进制字面量转换为编译期字符串 : http://www.purecpp.cn/detail?id=2375 [4] Inside STL: Smart pointers: https://devblogs.microsoft.com/oldnewthing/20230814-00/?p=108597 [5] Inside STL: The shared_ptr constructor vs make_shared: https://devblogs.microsoft.com/oldnewthing/20230815-00/?p=108602 [6] Inside STL: The shared_ptr constructor and enable_shared_from_this: https://devblogs.microsoft.com/oldnewthing/20230816-00/?p=108608 [7] C 23: mdspan: https://www.sandordargo.com/blog/2023/08/15/cpp23-mdspan-mdsarray [8] Transcoding UTF-8 strings to Latin 1 strings at 18 GB/s using AVX-512: https://lemire.me/blog/2023/08/12/transcoding-utf-8-strings-to-latin-1-strings-at-12-gb-s-using-avx-512/ [9] Some C 20 ranges aren’t const-iterable: https://quuxplusone.github.io/blog/2023/08/13/non-const-iterable-ranges/ [10] Writing custom C 20 coroutine systems: https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/coroutines-c 20/ [11] Parameter Passing in Flux versus Ranges: https://tristanbrindle.com/posts/parameter-passing-in-flux-vs-ranges [12] How to convert an enum to string in C : https://mariusbancila.ro/blog/2023/08/17/how-to-convert-an-enum-to-string-in-cpp/ [13] The New C Library: Strong Library Foundation for Future Projects - Jonathan Müller & Arno Schödl : https://www.youtube.com/channel/UCxHAlbZQNFU2LgEtiqd2Maw [14] asteria: https://github.com/lhmouse/asteria [15] Unilang: https://github.com/linuxdeepin/unilang [16] gcc-mcf: https://gcc-mcf.lhmouse.com/ [17] 本文永久链接: https://wanghenshui.github.io/cppweeklynews/posts/127.html

0 人点赞