C++ 中文周刊 第53期

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

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

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


资讯

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

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

文章

一个async对应一个future,别共用一个future,会阻塞

using my_map = unordered_map<{
  .key = type<int>, .value = type<std::string>,
  .allocator = type< my_allocator< std::pair<const int, std::string > > >
}>;

注意这个用法,说实话还是挺别扭。能省几行代码

有些类型是可以拷贝但不能比较的,比如function

STL中还有哪个组件类似?

constexpr std::monostate m;
static_assert(m == m);

std::monostate按理说就是个tag类型,比较没有意义,但是这里确实可以比较,本身有value语义

再比如

constexpr std::nullopt_t n;
bool b = (n == n);  // Error: does not compile!

nullopt明显没有value语义

通过把输出定向到 /dev/full 可以看到错误硬件错误,这是一个测试的好手段,可以判断如果调用了硬件接口报错是不是真的处理了错误码

$ echo "Hello World!" > /dev/full
bash: echo: write error: No space left on device
$ echo $?
1

但是c/c++是没有处理的

cat hello.c
/* Hello World in C, Ansi-style */

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  puts("Hello World!");
  return EXIT_SUCCESS;
}

gcc hello.c -o hello
./hello > /dev/full
echo $?
1

strace -etrace=write ./hello > /dev/full
write(1, "Hello World!\n", 13)          = -1 ENOSPC (No space left on device)
+++ exited with 0 +++

作者测试了其他语言,汇总了个表格,有些处理了,有些没处理。这里就不介绍了

用模板包装

class Car {
public:
  ~Car() = default;
  void startEngine() {
    // some implementation
  }
  
  int getTrunkSize() const {
    // some implementation
  }
  
  void addFuel(double quantity) {
    // some implementation
  }
};

class MockCar {
public:
  MOCK_METHOD(void, startEngine, (), ());
  MOCK_METHOD(int, getTrunkSize, (), (const));
  MOCK_METHOD(void, addFuel, (double quantity), ());
};

template <typename CarImpl>
class CarWrapper {
public:
  CarWrapper(C carImpl): _carImpl(carImpl) {}

  void startEngine() {
    _carImpl.startEngine();
  }
  
  int getTrunkSize() const {
    return _carImpl.getTrunkSize();
  }
  
  void addFuel(double quantity) {
    _carImpl.addFuel();
  } 
private:
  CarImpl _carImpl;
}


	

CarWrapper<MockedCar> c;

另外gmock也有新组件

TEST(CarMockTest, testStatementOrder) {
  ::testing::NiceMock<MockCar> c;
  EXPECT_CALL(c, startEngine()).Times(1);
  c.startEngine();
}

可以看googlemock/docs/CookBook.md 了解更多

经典循环展开,SWAR SIMD过程,具体的推导过程可以看原文,我这里直接贴代码了

union Pixel
{
    uint8_t c[4]; // four channels: red, green, blue, alpha
    uint32_t v;   // full pixel value as a 32-bit integer
};

void darken(Pixel* first, Pixel* last, int darkness)
{
  int lightness = 256 - darkness;
  for (; first < last; ++first) {
    for (int i = 0; i < 3; ++i) {
      first->c[i] = (uint8_t)(first->c[i] * lightness / 256);
    }
  }
}

//展开
void darken(Pixel* first, Pixel* last, int darkness)
{
  int lightness = 256 - darkness;
  for (; first < last; ++first) {
    first->c[0] = (uint8_t)(first->c[0] * lightness / 256);
    first->c[1] = (uint8_t)(first->c[1] * lightness / 256);
    first->c[2] = (uint8_t)(first->c[2] * lightness / 256);
  }
}

//算法拆解,省掉除法, SWAR

void darken(Pixel* first, Pixel* last, int darkness)
{
  int factor = darkness / 8;
  for (; first < last; ++first) {
    uint32_t v = first->v;
    uint32_t fields = (v & 0xFF) |
                     ((v & 0xFF00) << 2) |
                     ((v & 0xFF0000) << 4);
    fields *= factor;
    fields += pack_fields(31, 31, 31);
    uint32_t diff = ((fields >> 5) & 0x1F) |
                    ((fields >> 7) & 0x1F00) |
                    ((fields >> 9) & 0x1F0000) |
    first->v = v - diff;
  }
}

//SIMD改写

void darken(Pixel* first, Pixel* last, int darkness)
{
  int lightness = 256 - darkness;
  auto lightness128 = _mm_set_epi16(
        256, lightness, lightness, lightness,
        256, lightness, lightness, lightness);
  void* end = last;
  for (auto pixels = (__m128i*)first; pixels < end; pixels++) {
    auto val = _mm_loadu_si128(pixels);
    auto vlo = _mm_unpacklo_epi8(val, _mm_setzero_si128());
    vlo = _mm_mullo_epi16(vlo, alpha128);
    vlo = _mm_srli_epi16(vlo, 8);
    auto vhi = _mm_unpackhi_epi8(val, _mm_setzero_si128());
    vhi = _mm_mullo_epi16(vhi, alpha128);
    vhi = _mm_srli_epi16(vhi, 8);
    val = _mm_packus_epi16(vlo, vhi);
    _mm_storeu_si128(pixels, val);
  }
}

不太懂,windows平台的,这里标记个TODO

视频

除了放在模板参数里,还可以这样

consteval auto as_constant(auto value) { return value;}

template<typename ... Param>
consteval decltype(auto) consteval_invoke(Param && ... param) {
    return std::invoke(std::forward<Param>(param)...);
}

一般来说用不上

讲mock的

开源项目需要人手

新项目介绍/版本更新


本文永久链接

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