C++ 中文周刊 第72期

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

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

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

2022 0726 最近有点忙


资讯

标准委员会动态/ide/编译器信息放在这里 七月邮件汇总

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

文章

讲完美哈希表的。这个知识好像没怎么普及开,这里推荐一下

一个思路,禁止各种make,只能从静态函数构造

template<typename T>
struct require_make_shared :
    public std::enable_shared_from_this<T>
{
protected:
    struct use_the_create_method {
        explicit use_the_create_method() = default;
    };

public:
    template<typename...Args>
    static auto create(Args&&... args)
    {
        return std::make_shared<T>
            (use_the_create_method{},
             std::forward<Args>(args)...);
    }

    // Deny copy construction
    require_make_shared(require_make_shared const&) = delete;
};

class Widget : public require_make_shared<Widget>
{
public:
    Widget(use_the_create_method);
    Widget(use_the_create_method, int);
    Widget(use_the_create_method, int, int);
};

void test()
{
    auto v1 = Widget::create(); // okay
    auto v2 = std::make_shared<Widget>(); // nope
    auto v3 = std::make_unique<Widget>(); // nope
    Widget v4; // nope
}
std::string s{"there is a needle in the haystack"};
std::string_view sv{"acdef"};

if (s.contains("needle")) { // 总算有这个api了
    std::cout << "we found a needle in: " << std::quoted(s) << '\n';
}

if (!sv.contains('b')) {
    std::cout << "we did not find a 'b' in: " << std::quoted(sv) << '\n';
}

std::string s(nullptr); //不会挂了

basic_string::resize_and_overwrite() 可以省一个写,用不上的可以先用gcc内置函数

std::string s { "Food: " };
s.resize_and_overwrite(10, [](char* buf, int n) {
    return std::find(buf, buf + n, ':') - buf;
});
std::cout << "2. " << std::quoted(s) << '\n';

c23支持embed了,c++23还不支持std::embed。服了

介绍一下embed,看代码你就懂了

#include <assert.h>

int main (int, char*[]) {
	static const char sound_signature[] = {
#embed <sdk/jump.wav>
	};
	static_assert((sizeof(sound_signature) / sizeof(*sound_signature)) >= 4,
		"There should be at least 4 elements in this array.");

	// verify PCM WAV resource signature (at run-time)
	assert(sound_signature[0] == 'R');
	assert(sound_signature[1] == 'I');
	assert(sound_signature[2] == 'F');
	assert(sound_signature[3] == 'F');

	return 0;
}

定制formatter,代码不贴了

auto foo(auto&&);

int main() {
    int i{};
    const int c{};

    foo(42);       // int
    foo(i);        // int&
    foo(int{i});   // int
    foo(auto{i});  // int
    foo(auto(42)); // int
    foo(c);        // const int&
    foo(int{c});   // int
    foo(auto(c));  // int
}

这个也讲过很多次了。有些场景是需要copy语义的,否则莫名其妙出现了改动,解决办法就是让他退化,拿到copy

这个例子也说过很多次了

#include <iostream>

template<class T> 
constexpr std::decay_t<T>
decay_copy(T&& v)
    noexcept(std::is_nothrow_convertible_v<T, std::decay_t<T>>)           // exposition only
{
     return std::forward<T>(v);
}

int main() {
  std::vector<int> v1{1, 2, 1, 1, 1};
  auto v2 = v1;
  v1.erase(
      std::remove(begin(v1), end(v1), *std::max_element(begin(v1), end(v1))),
      v1.end());
  v2.erase(std::remove(
               begin(v2), end(v2),
               decay_copy(*std::max_element(begin(v2), end(v2)))),
           v2.end());
  std::cout << "v1.size()=" << v1.size() << std::endl 
            << "v2.size()=" << v2.size()
            << std::endl;
  return 0;
}

p2162继承variant各个编译器已经支持了。作者展示了一种优雅的用法

#include <cstdint>
#include <iostream>

using namespace std;

struct Request {
  static constexpr uint8_t id_num {1};
  uint8_t req_val;

  void encode(ostream& os) const {
    os.put(req_val);
  }

  void decode(istream& is) {
    req_val = is.get();
  }
};

struct Affirmative {
  static constexpr uint8_t id_num {2};
  uint8_t resp_val;

  void encode(ostream& os) const {
    os.put(resp_val);
  }

  void decode(istream& is) {
    resp_val = is.get();
  }
};

struct Failure {
  static constexpr uint8_t id_num {3};
  uint8_t resp_val;

  void encode(ostream& os) const {
    os.put(resp_val);
  }

  void decode(istream& is) {
    resp_val = is.get();
  }
};

#include <variant>
#include <exception>

struct Packet : variant<Request, Affirmative, Failure> {
  using variant::variant;

  Packet(uint8_t id) : variant {from_id(id)} {}

  Packet(istream& is) {
    decode(is);
  }

  void encode(ostream& os) const {
    visit([&](const auto& inner){
      os.put(inner.id_num);
      inner.encode(os);
    }, *this);
  }

  void decode(istream& is) {
    *this = from_id(is.get());
    visit([&](auto& inner){ inner.decode(is); }, *this);
  }

private:
  static Packet from_id(uint8_t id) {
    switch(id) {
      case Request::id_num:
        return Request {};
      case Affirmative::id_num:
        return Affirmative {};
      case Failure::id_num:
        return Failure {};
    }
    throw std::runtime_error {"Invalid Packet Id!"};
  }
};

#include <concepts>
#include <sstream>

#include <fmt/format.h>
using fmt::print;

int main(void) {
  Packet p {Request {.req_val {5}}};
  stringstream buf;

  p.encode(buf);

  Packet decoded {buf};
  visit([](const auto& inner){
    using T = decltype(auto(inner));
    if constexpr(same_as<T, Request>)
      print("I am a Request with a val of: {}", inner.req_val);
    else if constexpr(same_as<T, Affirmative>)
      print("I am an Affirmative with a val of: {}", inner.resp_val);
    else if constexpr(same_as<T, Failure>)
      print("I am a Failure with a val of: {}", inner.resp_val);
  }, decoded);
}

这种写法确实挺爽的,有点猥琐的模式匹配那个味了,https://godbolt.org/z/rqYeY5r1f

作者也展示了用concept达到类似的效果

#include <concepts>

struct Stranger {};

using Person = variant<Alice, Bob, Stranger>;

template <typename T>
concept IsNamed = requires(T p) {
  { p.name() } -> convertible_to<string_view>;
};

void print_name(Person& p) {
  visit([](auto& inner) {
    if constexpr(IsNamed<decltype(inner)>)
      print("Name: {}\n", inner.name());
    else
      print("This is a stranger!\n");
  }, p);
}

也不是不行,就是concept一般人比较不好接受

讲裁剪二进制的。

视频

通过函数make_lambda返回一个lambda,然后推导这个lambda的类型,就可以放到vector里了。直接用lambda不行,类型信息是匿名的,无法使用。 或者用std::function不就行了?

开源项目需要人手

新项目介绍/版本更新

说实话格局低了。自己开新坑不如隔壁meta推出新IR修缮 另外下一个c++不是rust么,都这么多年了,为啥会选你carbon,除非像go一样硬推

工作招聘

有没有需要招扫地僧式保洁的。我会拖地


本文永久链接

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