C++ 中文周刊 第25期

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

每周更新

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

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


资讯

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

本周周报github直达

文章

介绍了concept相比于rust traits的区别。不引入新的语法形式

主要是std::transform(std::execution::seq带来的并行优势

代码在这里

github.com/fenbf/articles/cpp17/CSV%20Reader/csv_reader.cpp 串行

github.com/fenbf/articles/cpp17/CSV%20Reader/csv_reader_par.cpp -并行

icc也切到llvm后端了?投入llvm的开发越来越多,针对功能实现的抉择也就多了起来,好事

介绍异常的方方面面,值得了解一下 (或者永远不用异常)

介绍了一个复杂的例子,如何用模板模板参数来改善CRTP复杂性

2021了不会还有人不知道变参模板吧

#include <iostream>
using namespace std::literals;
template <typename ... Args>
void printSize(Args&& ... args){
    std::cout << sizeof...(Args) << ' ';              // (1)
    std::cout << sizeof...(args) << '\n';             // (2)
}
int main() {
    std::cout << '\n';
    printSize();                                       // (3)
    printSize("C string", "C++ string"s, 2011, true);  // (4) 打印几?
    std::cout << '\n';
}

clang++上 -std=c++2b可用 不过也导致了一些问题,列出了问题的解决方案

视频

介绍c++20带来的std::cmp_xx函数

比较二个整数 tu 的值。不同于内建比较运算符,负有符号整数始终比较小于(且不等于)无符号整数:该比较相对于有损整数转换是安全的。

-1 > 0u; // true
std::cmp_greater(-1, 0u); // false

cppnow

cppnow 2021全放出来了。之前看了几个,陆陆续续看一看,只介绍我感兴趣的了

std::function不能处理move的场景

#include <functional>
#include <memory>

struct widget {
    // ...
};

int main() {
    std::function<void()> f = [w_ptr = std::make_unique<widget>()] {
        ...
    };
}

直接报错,所以要有支持move的f,any_invocable诞生,以前叫move_function/ function_ref改成这个了

这里有个实现 https://github.com/ofats/any_invocable/blob/master/include/ofats/invocable.h

ppt https://cppnow.digital-medium.co.uk/wp-content/uploads/2021/05/tfoai.pdf

这个视频就是介绍这个的原理,我看早晚进标准里

回顾了一下各种写库技巧,从tag dispatch到enable_if 到concept

一个测试框架的基本功能

对比googletest boost.test catch2 doctest

都是基于宏实现(gtest,btest,doctest),且集成困难(库的形式),要么就是编译慢(catch2)

这里介绍boostext.ut,一个不依赖宏的简单集成的测试框架

看代码

lconstexpr auto sum(auto... args) { return (0 + ... + args); }
import ut;               // C++20 module

int main() {
  "sum"_test = [] {      // Running... sum
     sum(1, 2) == 42_i;  // sum.cpp:5:FAILED [ 3 == 42 ]
  };                     // tests:   1 | 1 failed
}                        // asserts: 1 | 0 passed | 1 failed



suite sums = [] {
 "sum with no args"_test       = [] { expect(sum() == 0_i); };
 "sum with single arg"_test    = [] { expect(sum(42) == 42_i); };
 "sum with multiple args"_test = [] { expect(sum(1, 2) == 3_i); };
};

用的是用户定义字面量 UDL

后面就详细的解释ut的实现

struct test {
  std::string_view name{}; // test case name
  auto operator=(std::invocable auto test) -> void {
    std::clog << "Running... " << name << '\n';
    test();
  }
};
[[nodiscard]] constexpr concepts::test auto operator""_test(
  const char* name, std::size_t size) {
  return test{.name = {name, size}};
}

然后就是operator ==的实现

后面不介绍了

还定义了很多UDL,比如 _i

还有expect和suite的实现,不展开了,设计思路很有意思,从UDL入手,确实眼前一亮,但是,没有MOCK功能

为啥不用内建的整型 — > 被各种整形提升未定义行为折磨,放弃了

解决方案,enum as integers,不匹配直接爱咋咋地

// unsigned 
enum class ui8 : std::uint8_t { tag_to_prevent_mixing_other_enums };
enum class ui16: std::uint16_t{ tag_to_prevent_mixing_other_enums };
enum class ui32: std::uint32_t{ tag_to_prevent_mixing_other_enums };
enum class ui64: std::uint64_t{ tag_to_prevent_mixing_other_enums };
// signed
enum class si8 : std::int8_t { tag_to_prevent_mixing_other_enums };
enum class si16: std::int16_t{ tag_to_prevent_mixing_other_enums };
enum class si32: std::int32_t{ tag_to_prevent_mixing_other_enums };
enum class si64: std::int64_t{ tag_to_prevent_mixing_other_enums };

然后用UDL把值抠出来

inline namespace literals {
consteval
ui16 operator""_ui16(unsigned long long val) {
  if (val <= std::numeric_limits<std::underlying_type_t<ui16>>::max()) 
{
    return ui16(val);
  } else {
    throw "integral constant too large"; // trigger compile-time error
  }
}

然后围绕这个设定,补充traits/concept/assert等等。具体不展开了,还是UDL

项目


本文永久链接

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