C++ 动态新闻推送 第50期
从[reddit](https://www.reddit.com/r/cpp/)/[[hackernews](https://news.ycombinator.com/)](https://news.ycombinator.com/)/[[lobsters](https://lobste.rs/)](https://lobste.rs/)/[[meetingcpp](https://www.meetingcpp.com/blog/blogroll/items/Meeting-Cpp-Blogroll-317.html)](https://www.meetingcpp.com/blog/blogroll/items/Meeting-Cpp-Blogroll-317.html)摘抄一些c++动态
[周刊项目地址](https://github.com/wanghenshui/cppweeklynews)|[[在线地址](https://wanghenshui.github.io/cppweeklynews/)](https://wanghenshui.github.io/cppweeklynews/) |[知乎专栏](https://www.zhihu.com/column/jieyaren) |[腾讯云+社区](https://cloud.tencent.com/developer/column/92884)
弄了个qq频道,[手机qq点击进入](https://qun.qq.com/qqweb/qunpro/share?_wv=3&_wwv=128&inviteCode=xzjHQ&from=246610&biz=ka)
欢迎投稿,推荐或自荐文章/软件/资源等,请[提交 issue](https://github.com/wanghenshui/cppweeklynews/issues)
资讯
标准委员会动态/ide/编译器信息放在这里
c++ summit在上海要开,三月份,两天套票接近六千,真心贵,这价格,比cppcon还贵
[Visual Studio 2022 17.1 is now available!](https://devblogs.microsoft.com/visualstudio/visual-studio-2022-17-1-is-now-available/)
[编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-02-16 第137期](https://github.com/hellogcc/osdt-weekly/blob/master/weekly-2022/2022-02-16.md)
文章
- [Did you know that C++23 added Attributes on Lambda-Expressions?](https://github.com/QuantlabFinancial/cpp_tip_of_the_week/)
constexpr auto foo = [] [[deprecated]] { };
int main() {
foo(); // operator() is deprecated
}
Lambda 可以标注
主要是利用clang的 -ftime-trace
参数
我记得gcc也有一个类似的找不到了
- [C++ Templates: How to Iterate through std::tuple: std::apply and More](https://www.cppstories.com/2022/tuple-iteration-apply/)
承接上文啊,能实现遍历打印,肯定也能实现遍历调用lambda,如何实现呢?
核心代码,之前的index_sequence搬过来,另外还需要展开变参模版
for_each_tuple和之前的printtuple类似,for_each_tuple2避免难理解,主要是依赖lambda的模版能力,也是要展开变参模版
template <typename TupleT, typename Fn, std::size_t... Is>
void for_each_tuple_impl(TupleT&& tp, Fn&& fn, std::index_sequence<Is...>) {
(fn(std::get<Is>(std::forward<TupleT>(tp))), ...);
}
template <typename TupleT, typename Fn, std::size_t TupSize = std::tuple_size_v<std::remove_cvref_t<TupleT>>>
void for_each_tuple(TupleT&& tp, Fn&& fn) {
for_each_tuple_impl(std::forward<TupleT>(tp), std::forward<Fn>(fn), std::make_index_sequence<TupSize>{});
}
template <typename TupleT, typename Fn>
void for_each_tuple2(TupleT&& tp, Fn&& fn) {
std::apply
(
[&fn]<typename ...T>(T&& ...args)
{
(fn(std::forward<T>(args)), ...);
}, std::forward<TupleT>(tp)
);
}
- [Constant references are not always your friends](https://belaycpp.com/2022/02/15/constant-references-are-not-always-your-friends/)
虽然一般来说不需要拷贝的传参数用const T&就万事大吉,但是有些场景是不行的,比如T的设计不合理
我们要考虑T设计的问题,另外小对象,不要用const T&,比如string_view span int这种 直接传value
-
[c++ execution 与 coroutine (五):异步 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/441741987)
[c++ execution 与 coroutine (六):coroutine概述 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/443847625)
[c++ execution 与 coroutine (七):awaiter也是sender](https://zhuanlan.zhihu.com/p/445943412)
突然得知executor进不了c++23了,哎可惜。这些概念了解一下还是可以的。抽象程度很高
- [C++ Trailing Return Types](https://www.danielsieger.com/blog/2022/01/28/cpp-trailing-return-types.html)
讨论了一下把返回值放到后面的可行性,主要原因是作者开发的库经常会遇到这个返回值类型不确定的场景,比如
template<typename A, typename B>
decltype(std::declval<A>() * std::declval<B>()) multiply(A a, B b) { return a*b; }
- [The 114 standard C++ algorithms. Introduction](https://itnext.io/the-114-standard-c-algorithms-introduction-2a75a2df4300)
标准库的算法,了解一下
考虑一种场景,成员函数修饰调用限定
void Foo::bar() & { /* ... */ }
void Foo::bar() && { /* ... */ }
void Foo::bar() const & { /* ... */ }
void Foo::bar() const && { /* ... */ }
后面这种场景是为了限定Foo在某些类型的场景下才能调用
有了deducing this就能简化。举个例子
template <typename T>
class OptionalNotDeducingThis {
// ...
constexpr T* operator->() {
return addressof(this->m_value);
}
constexpr T const*
operator->() const {
return addressof(this->m_value);
}
// ...
};
template <typename T>
class OptionalDeducingThis {
// ...
template <typename Self>
constexpr auto operator->(this Self&& self) {
return addressof(self.m_value);
}
// ...
};
this Self来决定auto,所以你要const就 T* const,你不const的就T*
- [Faster integer formatting - James Anhalt (jeaiii)’s algorithm](https://jk-jeon.github.io/posts/2022/02/jeaiii-algorithm/)
一个证书序列化成字符串的算法(itoa)比fmt库内部的算法还要快,不过fmt作者没有考虑使用这个算法。
这里简单介绍一下
最简单的写法
char* itoa_naive(std::uint32_t n, char* buffer) {
char temp[10];
char* ptr = temp + sizeof(temp) - 1;
while (n >= 10) {
*ptr = char('0' + (n % 10));
n /= 10;
--ptr;
}
*ptr = char('0' + n);
auto length = temp + sizeof(temp) - ptr;
std::memcpy(buffer, ptr, length);
return buffer + length;
}
把整数序列化到temp数组,再拷贝出去,buf是10是因为int32就那么大
显然循环除10很慢,我们可以考虑减少循环次数,然后考虑除100
然后直接把余数给算好
首先想到的优化就是查表写数,而不是计算
static constexpr char radix_100_table[] = {
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4',
'0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
'1', '0', '1', '1', '1', '2', '1', '3', '1', '4',
'1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
'2', '0', '2', '1', '2', '2', '2', '3', '2', '4',
'2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
'3', '0', '3', '1', '3', '2', '3', '3', '3', '4',
'3', '5', '3', '6', '3', '7', '3', '8', '3', '9',
'4', '0', '4', '1', '4', '2', '4', '3', '4', '4',
'4', '5', '4', '6', '4', '7', '4', '8', '4', '9',
'5', '0', '5', '1', '5', '2', '5', '3', '5', '4',
'5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
'6', '0', '6', '1', '6', '2', '6', '3', '6', '4',
'6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
'7', '0', '7', '1', '7', '2', '7', '3', '7', '4',
'7', '5', '7', '6', '7', '7', '7', '8', '7', '9',
'8', '0', '8', '1', '8', '2', '8', '3', '8', '4',
'8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
'9', '0', '9', '1', '9', '2', '9', '3', '9', '4',
'9', '5', '9', '6', '9', '7', '9', '8', '9', '9'
};
char* itoa_two_digits_per_div(std::uint32_t n, char* buffer) {
char temp[8];
char* ptr = temp + sizeof(temp);
while (n >= 100) {
ptr -= 2;
std::memcpy(ptr, radix_100_table + (n % 100) * 2, 2);
n /= 100;
}
if (n >= 10) {
std::memcpy(buffer, radix_100_table + n * 2, 2);
buffer += 2;
}
else {
buffer[0] = char('0' + n);
buffer += 1;
}
auto remaining_length = temp + sizeof(temp) - ptr;
std::memcpy(buffer, ptr, remaining_length);
return buffer + remaining_length;
}
说实话这块我就看不懂了,后面更难了。这里标记个TODO,有时间研究一下
作者的一些优化经验,我看lamire老哥也关注了。写的很有噱头
- 2x faster GCD (compared to
std::gcd
)- 8-15x faster binary search (compared to
std::lower_bound
)- 7x faster segment trees
- 5x faster hash tables (compared to
std::unordered_map
)?x faster popcount- 2x faster parsing series of integers (compared to
scanf
)- ?x faster sorting (compared to
std::sort
)- 2x faster sum (compared to
std::accumulate
)- 10x faster array searching (compared to
std::find
)- 100x faster matrix multiplication (compared to “for-for-for”)
- optimal word-size integer factorization (~0.4ms per 60-bit integer)
- optimal Karatsuba Algorithm
- optimal FFT
- argmin at the speed of memory
文章很长一时半会看不完,这里先标记TODO了
- [Projections are Function Adaptors](https://brevzin.github.io/c++/2022/02/13/projections-function-adaptors/)
struct Person {
std::string first;
std::string last;
};
std::vector<Person> people = { /* ... */ };
std::vector<std::string> r_names;
std::ranges::copy_if(
people,
std::back_inserter(r_names),
[](std::string const& s) { return s[0] == 'R'; },
&Person::lastCommand Line Flags in C++
A Minimalist's Guide);
std::ranges::copy_if(
people | std::views::transform(&Person::last),
std::back_inserter(r_names),
[](std::string const& s) { return s[0] == 'R'; });
看懂这两段代码的区别了吗,第一段代码不工作,因为
视频
没啥说的
- [SIMD algorithms](https://www.youtube.com/watch?v=U1e_k8xmwR0&list=PLYCMvilhmuPEM8DUvY6Wg_jaSFHpmlSBD)
有时间可以看一下。simd感觉早晚得了解,躲不开
这里标记一个TODO,后面看了总结一下
开源项目需要人手
- [asteria](https://github.com/lhmouse/asteria) 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
- [pika](https://github.com/OpenAtomFoundation/pika) 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线
新项目介绍/版本更新
- [meta.hpp](https://github.com/blackmatov/meta.hpp) c++20反射库
- [log.c](https://github.com/rxi/log.c)一个log库,c的
看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!
[本文永久链接](