前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++ 中文周刊 第104期

C++ 中文周刊 第104期

作者头像
王很水
发布2023-03-11 09:48:36
3590
发布2023-03-11 09:48:36
举报

C++ 中文周刊 第104期

RSS https://github.com/wanghenshui/cppweeklynews/releases.atom

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

提交 issue

这周瞎忙一周,没来得及看


资讯

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

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

文章

TL;DR 使用enable_shared_from_this 一定要public继承

一波源码解读,brpc大家都懂懂,争取抄一个自己的rpc

空大讲execution的文章,感兴趣的看看

Daniel Lemire我觉得他的名字应该没人不知道吧。已经提及过很多次,性能专家

std::from_chars已经要比strtod快很多倍了,作者的fast_floatstd::from_chars还快

(前身是fast_double_parser,没切的建议切过去,API和std::from_chars相同)

这篇文章是案例顺带压测一下速度。不用看也知道是吊锤,这个库很多软件都用,比如clickhouse

就是SIMD 接口。没啥说的

代码语言:javascript
复制
#include <immintrin.h>

int main() {
    const std::vector a = {1, 2, 3, 4};
    const std::vector b = {5, 6, 7, 8};

    const auto va = _mm_loadu_si128((__m128i*)a.data());
    const auto vb = _mm_loadu_si128((__m128i*)b.data());
    const auto result = _mm_add_epi32(va, vb);

    std::vector<int> v(a.size());
    _mm_storeu_si128((__m128i*)v.data(), result);

    assert((std::vector{1 + 5, 2 + 6, 3 + 7, 4 + 8} == v));
}

讲trivial relocation的现状以及开源实现

T.r. types

Non-t.r. types

Throwing-move types

Rightward motion (`insert`)

Leftward motion (`erase`)

Non-pointer iterators

STL Classic (non-relocating)

std::copy

N/A

N/A

UB

std::copy_n

N/A

N/A

UB

UB

std::copy_backward

N/A

N/A

UB

cstring

memcpy

UB

UB

UB

SFINAE

memmove

UB

SFINAE

Qt

q_uninitialized_relocate_n

✓?

UB

UB

SFINAE

q_relocate_overlap_n

SFINAE

BSL

destructiveMove

UB

UB

SFINAE

P2786R0

trivially_relocate

SFINAE

SFINAE

SFINAE

relocate

SFINAE

SFINAE

move_and_destroy

SFINAE

UB

?

P1144R6

uninitialized_relocate

UB

uninitialized_relocate_n

UB

P1144R7

uninitialized_relocate_backward

UB

还给人folly提MR https://github.com/facebook/folly/pull/1934

这是个挺复杂的话题。了解一波

还是和trivial relocation相关的实现问题。看不懂

一些模版技巧介绍

CRTP没人不知道吧,想想enable_shared_from_this

overload用法,也就这么个例子

代码语言:javascript
复制
template<typename ... Ts> 
struct Overload : Ts ... { 
    using Ts::operator() ... ; 
};

策略模版,比如

代码语言:javascript
复制
template<class T, class Allocator std::allocator<T>>        
class vector; 

template<class Key,
    class T,
    class Hash = std::hash<Key>,                               
    class KeyEqual = std::equal_to<Key>,                       
    class allocator = std::allocator<std::pair<const Key, T>>  
class unordered_map;

Tag Dispatching 想想迭代器特化

Type Erasure 想想std::function,之前咱们也手挫过一个,往前翻翻回忆一下

先列一段装饰器模式的代码,其实就是策略模式

代码语言:javascript
复制
// taxed.h

#pragma once

#include "money.h"
#include "priced_item.h"
#include <utility>

template< int taxRate, PricedItem Item >
class Taxed : private Item  // Using inheritance
{
 public:
   template< typename... Args >
   explicit Taxed( Args&&... args )
      : Item{ std::forward<Args>(args)... }
   {}

   Money price() const {
      return Item::price() * ( 1.0 + (taxRate/100) );
   }
};

// priced_item.h

#pragma once

#include "money.h"

template< typename T >
concept PricedItem =
   requires ( T item ) {
      { item.price() } -> std::same_as<Money>;
   };

// money.h

#pragma once

#include <cmath>
#include <concepts>
#include <cstdint>
#include <ostream>

struct Money
{
   uint64_t value{};
};

template< typename T >
   requires std::is_arithmetic_v<T>
Money operator*( Money money, T factor )
{
   return Money{ static_cast<uint64_t>( money.value * factor ) };
}

constexpr Money operator+( Money lhs, Money rhs ) noexcept
{
   return Money{ lhs.value + rhs.value };
}

std::ostream& operator<<( std::ostream& os, Money money )
{
   return os << money.value;
}

// discounted.h

#pragma once

#include "money.h"
#include "priced_item.h"
#include <utility>

template< int discount, PricedItem Item >
class Discounted  // Using composition
{
 public:
   template< typename... Args >
   explicit Discounted( Args&&... args )
      : item_{ std::forward<Args>(args)... }
   {}

   Money price() const {
      return item_.price() * ( 1.0 - (discount/100) );
   }

 private:
   Item item_;
};

// cpp_book.h

#pragma once

#include "money.h"

#include <string>
#include <utility>

class CppBook
{
 public:
   CppBook( std::string name, Money price )
      : name_{ std::move(name) }
      , price_{ price }
   {}

   std::string const& name() const { return name_; }
   Money price() const { return price_; }

 private:
   std::string name_;
   Money price_;
};

// main.cpp

#include "conference_ticket.h"
#include "cpp_book.h"
#include "discounted.h"
#include "taxed.h"

#include <cstdlib>



int main()
{
   // 20% discount, 15% tax: (499*0.8)*1.15 = 459.08
   Taxed<15,Discounted<20,ConferenceTicket>> item{ "Core C++", Money{499} };
   Taxed<16,Discounted<21,ConferenceTicket>> item2{ "Core C++", Money{499} };
   Taxed<17,Discounted<22,CppBook>> item3{ "Core C++", Money{499} };

   Money const totalPrice = item.price();  // Results in 459.08
   Money const totalPrice2 = item2.price();
   Money const totalPrice3 = item3.price();
      // ...

   return EXIT_SUCCESS;
}   

比继承快多了

MSVC的能力介绍

chrome编译符号太大了。只能升级工具来解决这个问题。作者的吐槽文

组合函数,高阶函数,一个常规的写法

代码语言:javascript
复制
template <class F, class... Fs> 
constexpr auto compose(F &&arg, Fs &&...args) {
  return [
    fun = std::forward<F>(arg),
    ... functions = std::forward<Fs>(args)
  ] <class... Xs> (Xs &&...xs) mutable
    requires std::invocable<F, Xs...> {
    if constexpr (sizeof...(Fs)) {
      return compose(std::forward<Fs>(functions)...)(
        std::invoke(std::forward<F>(fun), 
                    std::forward<Xs>(xs)...));
    } else {
      return std::invoke(
        std::forward<F>(fun), 
        std::forward<Xs>(xs)...);
    }
  };
}

辣眼睛。有没有人类能看懂的?std::views::transform

代码语言:javascript
复制
using std::views::transform;
auto fgh = transform(h) | transform(g) | transform(f);
 
// Calculate f( g( h(x) ) )
auto fgh_x = ranges::single_view{42} | fgh; 
 
//fgh_x[0]

豁然开朗了家人们

代码语言:javascript
复制
template <class... Fs>
auto composer(Fs&&... functions) {
  using std::views::transform;
  return (transform(functions) | ...);
}

leetcode 56题,用stl算法怎么做?std::partial_sum

代码语言:javascript
复制
sort(intervals);
auto merged = views::partial_sum(intervals, [](auto curr, auto i){
    return curr.second >= i.first ? std::pair{curr.first, max(curr.second, i.second)} : i;
}) | views::adjacent_remove_if([](auto i1, auto i2){
    return i1.first == i2.first;
});
 
for (const auto& [i,j] : merged) {
    std::cout << i << " " << j << "\n";
}

很精彩的讲SWAR的文章,我还没有看完

hyperfine可以分析单测执行快慢。建议执行单测可以前面加上这个跑,每次统计测试运行时间长短,来分析代码哪里引入问题,这也是一个有趣的思路

总之测试压测之类的数据,都是有用的

代码分析慢的地方是结构体比较 opetator==慢了。这个没啥好讲的,主要在于前面发现问题的思路,提前发现问题,解决问题

老生常谈了。reserve提高局部性,改动只要一点点

代码语言:javascript
复制
 std::vector<std::string> tokenize(const std::string& s)
 {
   std::vector<std::string> result;
+  // Expect four fields or less in our input.
+  result.reserve(4);
   std::string::size_type f = 0;
   std::string::size_type p = s.find(':');

开源项目需要人手

  • asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线
  • Unilang deepin的一个通用编程语言,点子有点意思,也缺人,感兴趣的可以github讨论区或者deepin论坛看一看。这里也挂着长期推荐了
  • paozhu 国人开发的web库,和drogon联系过没共建而考虑自己的需求基于asio开发。感兴趣的可以体验一下,挂在这里长期推荐了

新项目介绍/版本更新

  • snitch 又一个测试框架,我怎么感觉我说过
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • C++ 中文周刊 第104期
    • 资讯
      • 文章
        • 开源项目需要人手
          • 新项目介绍/版本更新
          相关产品与服务
          腾讯云代码分析
          腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档