从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一样硬推
有没有需要招扫地僧式保洁的。我会拖地