C++ 中文周刊 第62期

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

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

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

2022年5月14日16:41:18更新,最近深圳暴雨居家办公导致啥也没干。周末补上

资讯

Visual Studio 2022 17.2 is now available! 支持c++20 /std:c++20

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

文章

复习一下c++17边角料哈, 结构化绑定支持自定义类型了,逆天

struct foo {
    int i{};
    std::string s{};
};

template <auto N>
const auto& get(const foo& f) {
    if constexpr (N == 0) {
        return f.i;
    } else if constexpr (N == 1) {
        return f.s;
    }
}

namespace std {
template <>
struct tuple_size<::foo> : integral_constant<std::size_t, 2> {};

template <std::size_t N>
struct tuple_element<N, ::foo> {
    using type = decltype(get<N>(std::declval<::foo&>()));
};
}  // namespace std

int main() {
    auto [i, s] = foo{.i = 42, .s = "str"};
    assert(42 == i);
    assert("str" == s);
}

又是一个c++协程的教程

void chop1(int* count, std::string& str) {
    for (int i = 0; i < *count; ++i) {
        str[i] = 0;
    }
}


void chop2(int* count, std::u8string& str) {
    for (int i = 0; i < *count; ++i) {
        str[i] = 0;
    }
}

但是,优化效果却不同,chop2能优化成memset

chop1(int*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&):
        mov     eax, DWORD PTR [rdi]
        test    eax, eax
        jle     .L1
        xor     eax, eax
.L3:
        mov     rdx, QWORD PTR [rsi]
        mov     BYTE PTR [rdx+rax], 0
        add     rax, 1
        cmp     DWORD PTR [rdi], eax
        jg      .L3
.L1:
        ret
chop2(int*, std::__cxx11::basic_string<char8_t, std::char_traits<char8_t>, std::allocator<char8_t> >&):
        mov     edx, DWORD PTR [rdi]
        test    edx, edx
        jle     .L6
        mov     rdi, QWORD PTR [rsi]
        xor     esi, esi
        jmp     memset
.L6:
        ret

为什么?指针问题。char * 由于历史原因,可以表达int,编译器默认指针收到影响,写str莫名其妙的影响到了count 所以这里的*count不会优化成不变量

当然不是说u8string是为了解决这个问题的,这个问题主要还是指针对于上下文的影响,对于简单函数,能避免指针影响的对象,就尽量用对象

压测代码在这里 https://quick-bench.com/q/k8S-i72re2G2phZLolIERVTiZJo

搜字符串boyer_moore_horspool_searcher 最快

也有avx512魔法 不过没有对比

这还有个老文章std::find() and memchr() Optimizations

不贴代码了,我也看不懂avx 512的东西,有兴趣的可以看看lamir大哥整的新活

对于一些小对象,使用move来省操作

比如

struct widget_id {
    std::string value;
};

widget_id id = get_widget_id();
widget widget = find_widget_by_id(std::move(id));

但是一开始widget_id可能不是这个样子的,可能是

struct widget_id {
    int value;
};

这时候就会有告警提醒,你这个move是没有任何作用的,因为int是trival 给他加上个空 析构函数就不是trival了

还有一种场景,有成员函数操作

// Remember to add power to this widget, if possible
widget_id id = get_widget_id();

if (wants_power_early()) {
    add_widget_power(std::move(id));
}

...

if (is_empty(id)) {
    // Nobody added power yet, let's do it now.
    add_widget_power(std::move(id));
}

struct widget_id
{
    int value;
    bool is_empty() const { return value == 0; }
    operator bool() const { return value != 0; }
};

//if (!id.is_empty())
//if (id) {

这种也导致move不了

针对上面的场景,又不想要告警,可以用

template<typename T>
constexpr decltype(auto) move_allow_trivial(T&& t) noexcept
{
    return std::move(t); // NOLINT
}

没啥说的,手把手教你用协程

视频

讲auto{} 在c++ 23中有了decay_copy的语义。说过很多次了

cppcon 2021

没啥说的,介绍graphblas api

微积分?和ML相关的?看不懂

开源项目需要人手

新项目介绍/版本更新

const my::detail::SomeClass<int>& var_ref = var;
// Name of variable type.
NAMEOF_TYPE_EXPR(var_ref) -> "my::detail::SomeClass<int>"
nameof::nameof_type<decltype(var_ref)>() -> "my::detail::SomeClass<int>"
NAMEOF_FULL_TYPE_EXPR(var_ref) -> "const my::detail::SomeClass<int>&"
nameof::nameof_full_type<decltype(var_ref)>() -> "const my::detail::SomeClass<int>&"
NAMEOF_SHORT_TYPE_EXPR(var_ref) -> "SomeClass"
nameof::nameof_short_type<decltype(var_ref)>() -> "SomeClass"

using T = const my::detail::SomeClass<int>&;
// Name of type.
NAMEOF_TYPE(T) ->"my::detail::SomeClass<int>"
nameof::nameof_type<T>() -> "my::detail::SomeClass<int>"
NAMEOF_FULL_TYPE(T) -> "const my::detail::SomeClass<int>&"
nameof::nameof_full_type<T>() -> "const my::detail::SomeClass<int>&"
NAMEOF_SHORT_TYPE(T) -> "SomeClass"
nameof::nameof_short_type<T>() -> "SomeClass"

my::detail::Base* ptr = new my::detail::Derived();
// Name of type, using rtti.
NAMEOF_TYPE_RTTI(*ptr) -> "my::detail::Derived"
NAMEOF_FULL_TYPE_RTTI(*ptr) -> "volatile const my::detail::Derived&"
NAMEOF_SHORT_TYPE_RTTI(*ptr) -> "Derived"

本文永久链接

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